2011-01-21 31 views
23

Tôi đã tạo ra một mẫu như sauTại sao không phải mẫu của tôi chấp nhận một danh sách initializer

template<typename T> 
void f(T const& t) { } 

tôi muốn cho điều này là có thể được gọi bằng container mà còn bởi danh sách khởi tạo. Tôi nghĩ rằng nó sẽ là initializer_list<int>, khi được gọi như sau.

f({1, 2, 3}); 

Nhưng GCC cư xử như thể nó không được tiêu chuẩn phù hợp

m.cpp: In function 'int main()': 
m.cpp:6:25: warning: deducing 'const T' as 'const std::initializer_list<int>' 
m.cpp:4:6: warning: in call to 'void f(const T&) [with T = std::initializer_list<int>]' 
m.cpp:6:25: warning: (you can disable this with -fno-deduce-init-list) 

bất cứ ai có thể giải thích làm thế nào tôi có thể làm cho công việc này mà không cần cảnh báo? Cảm ơn!

+5

Hmm có vẻ không may là SO nghĩ rằng thẻ 'initializer_list' đồng nghĩa với' initializer-list' -.- C++ 0x sẽ rơi nước mắt! –

+0

AFAICS, nó không được định nghĩa là một từ đồng nghĩa tại http://stackoverflow.com/tags/initializer-list/synonyms. Có một số logic tích hợp thay thế 'x_y' bằng' x-y' không? – sbi

+0

Ồ, đừng bận tâm, tôi chỉ thấy http://meta.stackexchange.com/questions/75798/unfortunate-auto-detection-of-synonyms-for-initializer-list – sbi

Trả lời

25

Một "điều" như {1,2,3} không đủ điều kiện làm biểu thức. Nó không có loại. Do đó, không có khấu trừ loại nào được thực hiện. Nhưng C++ 0x làm cho một ngoại lệ rõ ràng cho 'auto', vì vậy

auto x = {1,2,3}; 

thực sự hoạt động và decltype (x) sẽ initializer_list<int>. Nhưng đây là một quy tắc đặc biệt chỉ áp dụng cho tự động. Tôi đoán họ muốn tạo các vòng như thế này

for (int x : {2,3,5,7,11}) { 
    ... 
} 

làm việc vì loại vòng này khai thác quy tắc đặc biệt.

Đối với việc giải quyết vấn đề, bạn có thể thêm một tình trạng quá tải initializer_list<T> như là một "wrapper":

template<class T> 
inline void outer(initializer_list<T> il) { 
    inner(il); 
} 

tôi đã không kiểm tra này, nhưng sự hiểu biết hiện tại của tôi là nó sẽ làm việc.

+1

+1 và để chính xác. –

+2

Quy tắc đặc biệt được đề cập trong 7.1.6.4 định danh 'tự động '[dcl.spec.auto] –

+0

' C++ 0x tạo ngoại lệ rõ ràng cho' tự động'', trong cả cú pháp giống như gán cho bạn và cũng là dạng 'auto something {a, b, c}'. Cái thứ hai đã là một nỗi đau không nhất quán ở hậu sau mà chỉ bây giờ sẽ được sửa với C++ 17, trong đó 'auto something {blah}' không có ký tự '=' có nghĩa là _'create một đối tượng 'decltype (blah) ', được khởi tạo từ' blah'_ - không phải là nghĩa hiện tại của _'tạo một 'initializer_list' được gọi là' something' với một phần tử có cùng kiểu với 'blah''_. Cuối cùng! Nhưng vào thời điểm này nó có nghĩa là rất nhiều cập nhật cho codebases bị ảnh hưởng. : C –

3

Vâng, the documentation nói rằng

Tùy chọn này có mặt vì khấu trừ đây là một mở rộng của đặc điểm kỹ thuật hiện tại trong C++ 0x dự thảo làm việc, và đã có một số lo ngại về vấn đề giải quyết tình trạng quá tải tiềm năng.

Thông tin này có thể đơn giản là lỗi thời (theo nguồn được cập nhật lần cuối vào năm 2008). Theo như tôi hiểu điều này, khoản khấu trừ đã được đưa vào GCC nhưng với kỳ vọng rằng dự thảo sau này của tiêu chuẩn sẽ loại bỏ quy tắc, hoặc ít nhất là hạn chế nó.

1

Mọi người có thể giải thích cách tôi có thể thực hiện tác phẩm này mà không có cảnh báo không?

Tôi không biết nếu this đề cập đến các mã chính xác mà bạn trích dẫn, hoặc nếu bạn chỉ muốn biết làm thế nào bạn có thể nhanh chóng các chức năng mẫu với một danh sách initializer mà không gây ra cảnh báo, nhưng nếu đó là thứ hai và nếu vấn đề là chỉ đơn thuần deducing đúng loại, bạn có thể có thể tránh điều đó bằng cách gọi

f<initializer_list<int>>({1, 2, 3}); 

nó không đẹp, nhưng nó có thể tránh được những cảnh báo mà không cần loay hoay với các đối số dòng lệnh biên dịch.

Tôi có thể đặt nhận xét gần đó giải thích rằng bạn không dựa vào trình biên dịch loại bỏ đúng loại do điểm yếu trong các phiên bản GCC nhất định.

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