Referencia de reenvío de C++ y referencia de valor r

3 minutos de lectura

avatar de usuario
dave

Entiendo que una referencia de reenvío es “una referencia de valor real a un parámetro de plantilla no calificado de cv”, como en

template <class T> void foo(T&& );

lo que significa que la función anterior puede tomar como referencia tanto el valor l como el valor r.

Hay algo que no entiendo, por ejemplo

template <class T>
class A
{
    template <class U>
    void foo(T&& t, U&& u)
    {
        T t2( std::forward
        U u2( std::forward(u) ); // or should it be std::move(u)? I believe U&& is forwarding reference
    }
};

en el código anterior, ¿Son T&& y U&& referencias de reenvío?

Escribí un código para probar (compilador VS2015):

class A
{
public:
    A(){};
    A(const A& rhs)
    {
        std::cout << "calling 'const A&' l-value" << std::endl;
    }

    A(A&& rhs)
    {
        std::cout << "calling ' A&&' r-value" << std::endl;
    }

};

template <class T>
class Test
{
public:
    void test1(T&& t)
    {
        T t2(std::forward<T>
    }

    template <typename X>
    void test2(X&& x)
    {
        T t2( std::forward<T>( x ) );
    }

};

void main()
{
    A a;
    Test<A> test;
    test.test1(A());
    test.test1(std::move(a));
    //test.test1(a); // this doesn't compile. error: cannot convert argument 1 from 'A' to 'A &&', You cannot bind an lvalue to an rvalue reference

    test.test2<A>(A());
    test.test2<A>( std::move( a ) );

    //test.test2<A>( a ); // this doesn't compile. error: cannot convert argument 1 from 'A' to 'A &&', You cannot bind an lvalue to an rvalue reference
}

Esperaba que test.test1(a); y test.test2(a) deberían compilarse si están reenviando referencias, pero ninguno lo hace.

¿Podría alguien explicarme esto? ¡Gracias!

Editar
————–gracias, muchachos———– Richard y Artemy tienen razón.

  • Sin relación, no sé si es triste o surrealista que, hoy en día, la cadena de herramientas VS2015 acepte void main(). En serio ?

    – WhozCraig

    1 de septiembre de 2017 a las 8:50


  • En su último caso cerrado, U no se deduce, por lo que su caso no se compilará. Para hacerlo deducible, llámelo test.test2( a ); y dentro de la prueba 2 cambia adelante a adelante

    – Artemy Vysotsky

    1 de septiembre de 2017 a las 9:05

Es una gran pregunta que los zorros casi todo el mundo al principio.

template <class T>
class A
{
    template <class U>
    void foo(T&& t, U&& u);
};

En este ejemplo, T no se deduce (usted lo define explícitamente cuando instancia la plantilla).

U se deduce porque se deduce del argumento u.

Por tanto, en casi todos los casos sería:

std::move
std::forward<U>(u);

  • POR CIERTO std::forward<T>

    – Jarod42

    1 de septiembre de 2017 a las 8:57

¿Son T&& y U&& referencias de reenvío?

No solo U&& es un referencia de reenvíoporque U es el único argumento de plantilla que se deduce. T ya fue "elegido" al instanciar A.

Además de lo que señalaron Richard y Artemy, cuando especificó test.test2<A>( a )el tipo X ya está explícitamente definido como A.

Cuando lo cambias a test.test2( a )entonces se debe deducir el tipo X y se debe compilar.

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad