C ++转发参考和r值参考

Dav*_*ve 4 c++ rvalue-reference forwarding-reference

我知道转发引用是“对cv不合格模板参数的右值引用”,例如

template <class T> void foo(T&& );
Run Code Online (Sandbox Code Playgroud)

这意味着上述函数可以同时使用l值和r值参考。

我有些不懂的事,例如

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

在上面的代码中,T &&和U &&都是转发参考吗?

我写了一些代码进行测试(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>(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
}
Run Code Online (Sandbox Code Playgroud)

我期待的是test.test1(a); 如果test.test2(a)正在转发引用,则两者都应编译,但两者都不会。

有人可以向我解释吗?谢谢!

编辑 --------------谢谢,伙计们-----------理查德(Richard)和阿尔蒂(Artemy)是正确的。

Vit*_*meo 8

T&& 和 U&& 都是转发参考吗?

不, onlyU&&是一个转发引用,因为U它是唯一被推导的模板参数。T实例化时已被“选择” A


Ric*_*ges 5

这是一个很大的问题,一开始几乎困扰着每个人。

template <class T>
class A
{
    template <class U>
    void foo(T&& t, U&& u);
};
Run Code Online (Sandbox Code Playgroud)

在此示例中,T未推导(实例化模板时您明确定义了它)。

U被推论是因为它是从论证推论得到的u

因此,几乎在所有情况下都是:

std::move(t);
std::forward<U>(u);
Run Code Online (Sandbox Code Playgroud)

  • 顺便说一句,在这种情况下,“std::forward&lt;T&gt;(t);”相当于“std::move(t);”(但不太明确)。 (2认同)