2015-02-06 13 views
10

Initializer danh sách biểu thức là thực sự thuận tiện cho việc khởi tạo C++ container:Forwarding danh sách initializer biểu thức

std::vector<int>({1, 2, 3}) 

... nhưng có vẻ như một biểu hiện danh sách initializer cú đúp kín, giống như {1,2,3} sẽ chỉ bám vào một chức năng mà phải mất một std::initializer_list<int> - nó không dường như liên kết với một phổ quát (chuyển tiếp) tham khảo:

template <class T> 
void foo(T&& v) 
{ 
    std::vector<int>(std::forward<T>(v)); 
} 

int main() 
{ 
    foo({1, 2, 3}) 
} 

đầu ra này:

test2.cpp:11:6: note: template<class U> void foo(U&&) 
test2.cpp:11:6: note: template argument deduction/substitution failed: 
test2.cpp:33:13: note: couldn't deduce template parameter ‘U’ 

(Đây là kết quả với GCC 4.7.2.)

này không may có nghĩa là chúng ta không thể chuyển tiếp một biểu danh sách initializer. Vì nó sẽ rất thuận tiện để làm điều đó, tôi muốn hỏi tại sao nó không hoạt động? Tại sao không thể có một biểu thức danh sách khởi tạo kèm cặp ngoặc đơn liên kết với tham chiếu chuyển tiếp? Hoặc là điều này được cho phép, và có lẽ trình biên dịch của tôi chỉ là quá cũ?

+1

Không sử dụng để chuyển tiếp một 'initializer_list': Nó đã có ngữ nghĩa tham chiếu, và các phần tử của nó là const, do đó không thể di chuyển được. – dyp

+0

Không quan trọng nếu chúng di chuyển được - một tham chiếu chuyển tiếp phổ quát không nhất thiết ngụ ý di chuyển, nó chỉ ngụ ý chuyển tiếp dọc theo tham số là – Siler

+3

Có, nhưng một danh sách-init-brace không có kiểu. Do đó, bạn không thể chuyển tiếp nó "as-is". – dyp

Trả lời

10

Nó không phải là nó không thể liên kết với tham số của hàm của bạn; nó chỉ là trình biên dịch không thể phát hiện loại mẫu của bạn. Biên dịch này:

#include <vector> 

template <class T> 
void foo(T&& v) 
{ 
    std::vector<int>(std::forward<T>(v)); 
} 

int main() 
{ 
    foo(std::initializer_list<int>{1, 2, 3}); 
} 
3

Không thể suy ra danh sách khởi tạo trong trường hợp này. Đây thực sự là bao phủ một cách rõ ràng bởi các tiêu chuẩn trong [temp.deduct.call]: trích lập luận

Template đượ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 kiểu của đối số tương ứng của gọi (gọi số A) như được mô tả bên dưới. Nếu P là một loại phụ thuộc, [...]. Nếu không, một đối số của trình khởi tạo làm cho tham số được coi là một ngữ cảnh không được suy luận (14.8.2.5). [Ví dụ:

template<class T> void f(std::initializer_list<T>); 
f({1,2,3}); // T deduced to int 
f({1,"asdf"}); // error: T deduced to both int and const char* 

template<class T> void g(T); 
g({1,2,3}); // error: no argument deduced for T 

Ví dụ dưới đây cho g là chính xác trường hợp của bạn - T không phải là một loại phụ thuộc, vì vậy đây được coi là một bối cảnh phi suy luận. Trình biên dịch là chính xác để từ chối mã của bạn.

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