2015-05-20 35 views
13

Tôi đang cố gắng hiểu các tham chiếu rvalue. Tôi đã thấy cách thức chúng được sử dụng trong nhà xây dựng, với những thứ như std::movestd::forward, nhưng tôi vẫn không hiểu tại sao điều này không làm việc:C++, tham chiếu rvalue trong tham số chức năng

void func(string&& str) 
{ 
    cout << str << endl; 
} 
int main(int argc, char* argv[]) 
{ 
    string s("string"); 
    func(s); 
} 

Và điều này:

template<typename T> 
void func(T&& str) 
{ 
    cout << str << endl; 
} 
int main(int argc, char* argv[]) 
{ 
    string s("string"); 
    func(s); 
} 

Tại sao nó có hoạt động với phiên bản mẫu chức năng không?

+4

Phiên bản thứ hai hoạt động vì 'T' được suy ra là' chuỗi & '."Khi kiểu tham số hàm có dạng T && trong đó T là một tham số mẫu, và đối số hàm là một giá trị của loại A, loại A & được sử dụng để khấu trừ đối số mẫu." Sử dụng 'std :: move' nếu bạn muốn cái cũ hoạt động. –

+0

Đây là trường hợp đặc biệt của việc khấu trừ mẫu, ở đây (và chỉ ở đây AFAIK), 'T' có thể được suy ra theo kiểu tham chiếu. Thông thường trong việc khấu trừ kiểu mẫu 'T' chỉ được suy luận như là một tham chiếu không. –

+1

có thể trùng lặp của [Cú pháp cho các tham chiếu chung] (http://stackoverflow.com/questions/14302849/syntax-for-universal-references) –

Trả lời

14

Giống như @ Peter cho biết, loại T là suy luận như string&, và cai trị tham khảo-sụp đổ C++ 's nói:

T & & ⇒ T & // từ C++ 98
T & & & ⇒ T & // mới cho C++ 0x
T & & & ⇒ T & // mới cho C++ 0x
T & & & & ⇒ T & & // mới cho C++ 0x

Vì vậy func ‘s instantiation thực sự là:

void func(string& str) 

Và nó hoạt động.

6

Một số lời giải thích chính thức, thêm vào câu trả lời @ songyuanyao của:

N4296::14.8.2.1 [temp.deduct.call]:

Template trích lập luận được thực hiện bằng cách so sánh từng chức năng kiểu mẫu tham số (gọi nó là P) với các loại tương ứng đối số của cuộc gọi (gọi là A) như được mô tả bên dưới.

N4296::14.8.2.1/3 [temp.deduct.call]:

Tham chiếu chuyển tiếp là một tài liệu tham khảo rvalue đến một cv-không đủ tiêu chuẩn tham số mẫu. Nếu P là tham chiếu chuyển tiếp và đối số là một giá trị, loại "lvalue tham chiếu đến A" được sử dụng thay cho A để khấu trừ loại.

Tiêu chuẩn cũng cung cấp các ví dụ sau:

template <class T> int f(T&& heisenreference); 
template <class T> int g(const T&&); 
int i; 
int n1 = f(i); // calls f<int&>(int&) 
int n2 = f(0); // calls f<int>(int&&) 
int n3 = g(i); // error: would call g<int>(const int&&) 

Đó chính là trường hợp của bạn.

Các vấn đề liên quan