"Se um trabalhador quiser fazer bem o seu trabalho, ele deve primeiro afiar suas ferramentas." - Confúcio, "Os Analectos de Confúcio. Lu Linggong"
Primeira página > Programação > Por que std::forward usa o modelo de identidade para desabilitar a dedução de argumentos do modelo?

Por que std::forward usa o modelo de identidade para desabilitar a dedução de argumentos do modelo?

Publicado em 2024-11-09
Navegar:757

Why does std::forward use the identity template to disable template argument deduction?

Desativando a dedução de argumentos do modelo com std::forward para garantir o encaminhamento correto

Considere a definição de std::forward no VS2010:

template inline
_Ty&& forward(typename identity<_Ty>::type& _Arg)
{   // forward _Arg, given explicitly specified type parameter
    return ((_Ty&&)_Arg);
}

O objetivo do modelo de identidade é desabilitar a dedução de argumentos do modelo. Por que isso é crucial neste cenário?

A dedução do argumento do modelo levaria à dedução de tipo incorreta. Se uma referência de rvalue a um objeto do tipo X for passada para uma função de modelo com um tipo de parâmetro T&, a dedução do argumento do modelo inferiria T como X, resultando em um tipo de parâmetro X&. Porém, para um encaminhamento perfeito, o parâmetro é um lvalue porque possui um nome. Portanto, usar a dedução de argumento de modelo em std::forward faria com que o tipo de parâmetro deduzido fosse uma referência lvalue ou uma referência const lvalue.

template
T&& forward_with_deduction(T&& obj)
{
    return static_cast

Considere o seguinte exemplo:

void test(int&){}
void test(const int&){}
void test(int&&){}

template
void perfect_forwarder(T&& obj)
{
    test(forward_with_deduction(obj));
}

int main()
{
    int x;
    const int& y(x);
    int&& z = std::move(x);

    test(forward_with_deduction(7));    //  7 is an int&&, correctly calls test(int&&)
    test(forward_with_deduction(z));    //  z is treated as an int&, calls test(int&)

    //  All the below call test(int&) or test(const int&) because in perfect_forwarder 'obj' is treated as
    //  an int& or const int& (because it is named) so T in forward_with_deduction is deduced as int& 
    //  or const int&. The T&& in static_cast<T&&>(obj) then collapses to int& or const int& - which is not what 
    //  we want in the bottom two cases.
    perfect_forwarder(x);           
    perfect_forwarder(y);           
    perfect_forwarder(std::move(x));
    perfect_forwarder(std::move(y));
}

Neste exemplo, o encaminhamento perfeito falha porque o parâmetro em perfect_forwarder é tratado como uma referência lvalue ou const lvalue devido ao seu nome. Isso leva à dedução de tipo incorreta em forward_with_deduction, resultando em semântica static_cast indesejada.

Desativar a dedução de argumento de modelo com o modelo de identidade em std::forward garante que std::forward sempre retorne uma referência de rvalue, o que é essencial para correto encaminhamento perfeito de lvalues, bem como de rvalues.

Tutorial mais recente Mais>

Isenção de responsabilidade: Todos os recursos fornecidos são parcialmente provenientes da Internet. Se houver qualquer violação de seus direitos autorais ou outros direitos e interesses, explique os motivos detalhados e forneça prova de direitos autorais ou direitos e interesses e envie-a para o e-mail: [email protected]. Nós cuidaremos disso para você o mais rápido possível.

Copyright© 2022 湘ICP备2022001581号-3