Có vẻ như đối số gói có thể được mở rộng chỉ thay cho thông số gói của mẫu bí danh. Đây không phải là đúng đối với một lớp hoặc một hàm template:Mở rộng gói cho mẫu bí danh
template <class T, class... Args> struct x { using type = T; };
template <class T, class... Args> using x_t = typename x<T, Args...>::type;
template <class... Args> using x_fix_t = typename x<Args...>::type;
template <class... Args> auto f(Args...) -> void {
typename x<Args...>::type v1; // OK
x_t<Args...> v2; // Error
x_fix_t<Args...> v3; // OK
}
đơn giản trường hợp:
template <class T, class U> using y_t = T;
template <class... Args> auto f(Args...) -> void {
y_t<Args...> v4; // Error
}
Đoạn mã trên tạo ra lỗi (thậm chí nếu f
không bao giờ được khởi tạo) với cả hai c++11
và c++14
trong g++ 4.9
, g++ 5.1
và clang 3.5
.
Tại sao điều này không được phép và quy tắc chung là gì? Tôi không thấy lý do nào để hạn chế điều này. Có vẻ như một lệnh cấm rất lạ.
Vì lý do tại sao không viết là x_fix_t
với biến thể đầu tiên, rõ ràng hơn là x_t
có đối số đầu tiên bắt buộc. (ví dụ đó là lý do f()
không được phép). Nhưng điều này không quan trọng, việc sửa chữa rất dễ dàng. Câu hỏi còn lại: Tại sao?
gcc lỗi:
error: pack expansion argument for non-pack parameter ‘T’ of
alias template ‘template<class T, class ... Args> using x_t = typename x::type’
kêu vang lỗi:
error: pack expansion used as argument for non-pack parameter of
alias template x_t<Args...> v2;
Thông tin ở đây có liên quan, tôi nghĩ: http://stackoverflow.com/q/24433658/4326278 – bogdan
Ngoài ra, đối với những gì nó có giá trị, MSVC 12 và 14 RC biên dịch điều này mà không có chẩn đoán (ngoài cảnh báo bình thường cho unreferenced biến) - "phương sai triển khai", như họ nói. – bogdan
Hoạt động OK trong g ++ 4.8.2. –