2017-09-01 169 views
2

我明白,一個轉發參考是「一個rvalue參照CV-不合格模板參數」,如在C++轉發參考和右值參考

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

這意味着上述功能可以採取兩個升值和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 
    } 
}; 
在上面的代碼

兩者是叔& &和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 
} 

我期待那test.test1(一);和test.test2(a)都應該在轉發引用時進行編譯,但都不是。

有人可以解釋這一點給我嗎?謝謝!

編輯 --------------謝謝,夥計們----------- 理查德和Artemy是正確的。

+2

無關,我不知道它在這個時代是VS2015工具鏈接受'void main()'的悲傷還是超現實。真的嗎? – WhozCraig

+0

在你上一次關閉的情況下,U不會被推斷 - 所以你的情況不會被編譯。爲了使其可以被稱爲test.test2(a);和內部測試2改變轉發

回答

2

這是一個很好的問題,狐狸幾乎每個人都在開始。

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

在這個例子中,T不是推斷(當你實例化模板,你明確地定義它)。

U推導出來是因爲它是從參數u中推導出來的。

因此,在幾乎所有情況下,這將是:

std::move(t); 
std::forward<U>(u); 
+0

順便說一句'std :: forward (t);'將等同於'std :: move(t);'是這種情況(但不太明確)。 – Jarod42

2

兩者是叔& &和U & &轉發引用?

沒有,只有U&&轉發參考,因爲U是真實而推導出的唯一模板參數。在實例化A時已經「選擇」了T