2016-02-15 16 views
10

Theo MSVC, gcc và kêu vang, đoạn mã sau là bất hợp pháp:Sử dụng một lớp mẫu trong một hàm mẫu với tham số tài liệu tham khảo phổ

template <typename T> 
void f(T&& e) { 
    std::vector<T> v; 
    // do something with v and e ... 
} 
int main() { 

    int i; 
    f(i); 
} 

sản lượng msvc

xmemory0 (591): Lỗi C2528: 'con trỏ': con trỏ để tham chiếu là bất hợp pháp

gcc và clang cung cấp các thông báo lỗi tương tự. Lưu ý rằng tham số tham chiếu phổ dụng e không được sử dụng. Trình biên dịch rõ ràng là thất bại trong việc nhanh chóng các vector v, phàn nàn về nó được sử dụng với một tham chiếu đến int:

lưu ý: xem tham chiếu đến lớp mẫu instantiation 'std::vector<T,std::allocator<_Ty>>' được biên soạn với

[ 
     T=int &, 
     _Ty=int & 
    ] 

Nhưng tôi không thể thấy nơi mẫu chức năng f được khởi tạo với tham chiếu đến int.

Ai đó có thể giải thích các lỗi trình biên dịch mà chúng ta thấy ở đây?

+5

Lưu ý rằng * tham chiếu chuyển tiếp * hiện là thuật ngữ ưa thích. – TartanLlama

Trả lời

18

Khi f được gọi với một giá trị trái int, T sẽ được suy luận như int&, vì vậy v sẽ là một std::vector<int&>. Điều này không hợp lệ.

Một cách để làm được việc này là để loại bỏ các tham chiếu từ T trước khi sử dụng nó:

template <typename T> 
void f(T&& e) { 
    using value_type = typename std::remove_reference<T>::type; 
    //using value_type = std::remove_reference_t<T>; for C++14 
    std::vector<value_type> v; 
    // do something with v and e ... 
} 

Tuy nhiên, nếu bạn muốn các chức năng để được chung chung kiểu như có thể, bạn nên sử dụng std::decay thay vì std::remove_reference. Điều này sẽ cho phép f hoạt động với các loại, mảng và chức năng đủ điều kiện cv.

+2

Mặc dù 'C++ 11' được gắn thẻ, có lẽ cũng đề xuất' remove_reference_t' chỉ trong trường hợp? Nó làm cho nó một lớp lót đẹp. –

+0

@YamMarcovic Cảm ơn, tôi đã thêm vào đó, mặc dù tôi muốn làm điều đó trên hai dòng hơn một. – TartanLlama

+0

Một lưu ý cho người đọc: Tôi muốn nhấn mạnh rằng vì f là mẫu hàm ngay cả T trong std :: vector trở thành T & khi f được khởi tạo với một giá trị, theo các quy tắc mà câu trả lời trích dẫn. Trước đây, sự hiểu biết của tôi là T trong std :: vector không thể khác với T trong . –

7

Scott Meyers giải thích trong số article này.

Nếu biểu thức khởi tạo tham chiếu chung là một giá trị, tham chiếu chung trở thành tham chiếu giá trị.

Nếu biểu thức khởi tạo tham chiếu chung là giá trị, tham chiếu phổ biến trở thành tham chiếu giá trị.

Trong trường hợp của bạn i là một giá trị trái và do đó T là suy luận như int&.

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