"Si un trabajador quiere hacer bien su trabajo, primero debe afilar sus herramientas." - Confucio, "Las Analectas de Confucio. Lu Linggong"
Página delantera > Programación > ¿Por qué std::forward usa la plantilla de identidad para deshabilitar la deducción de argumentos de plantilla?

¿Por qué std::forward usa la plantilla de identidad para deshabilitar la deducción de argumentos de plantilla?

Publicado el 2024-11-09
Navegar:624

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

Deshabilitar la deducción de argumentos de plantilla con std::forward para garantizar un reenvío correcto

Considere la definición de std::forward en VS2010:

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

El propósito de la plantilla de identidad es deshabilitar la deducción de argumentos de la plantilla. ¿Por qué es esto crucial en este escenario?

La deducción de argumentos de plantilla conduciría a una deducción de tipos incorrectos. Si una referencia rvalue a un objeto de tipo X se pasa a una función de plantilla con un tipo de parámetro T&, la deducción del argumento de la plantilla inferiría que T es X, lo que daría como resultado un tipo de parámetro X&. Sin embargo, para un reenvío perfecto, el parámetro es un valor l porque tiene un nombre. Por lo tanto, usar la deducción de argumentos de plantilla en std::forward causaría que el tipo de parámetro deducido sea una referencia de valor l o una referencia de valor l constante.

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

Considere el siguiente ejemplo:

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));
}

En este ejemplo, el reenvío perfecto falla porque el parámetro en perfect_forwarder se trata como una referencia lvalue o const lvalue debido a su nombre. Esto lleva a una deducción de tipos incorrecta en forward_with_deduction, lo que resulta en una semántica static_cast no deseada.

Deshabilitar la deducción de argumentos de plantilla con la plantilla de identidad en std::forward garantiza que std::forward siempre devuelva una referencia rvalue, que es esencial para correcto reenvío perfecto de lvalues ​​y rvalues.

Último tutorial Más>

Descargo de responsabilidad: Todos los recursos proporcionados provienen en parte de Internet. Si existe alguna infracción de sus derechos de autor u otros derechos e intereses, explique los motivos detallados y proporcione pruebas de los derechos de autor o derechos e intereses y luego envíelos al correo electrónico: [email protected]. Lo manejaremos por usted lo antes posible.

Copyright© 2022 湘ICP备2022001581号-3