15

tôi có mã:Chuyên tham số mẫu mẫu biến thể trên số lượng đối số tối thiểu: hợp pháp hay không?

#include <cstdio> 

template<template<typename...> class> 
struct Foo 
{ 
    enum { n = 77 }; 
}; 

template<template<typename, typename...> class C> 
struct Foo<C> 
{ 
    enum { n = 99 }; 
}; 

template<typename...> struct A { }; 

template<typename, typename...> struct B { }; 

int main(int, char**) 
{ 
    printf("%d\n", Foo<A>::n); 
    printf("%d\n", Foo<B>::n); 
} 

Ý tưởng là template<typename, typename...> class là một tập hợp con của template<typename...> class, vì vậy nó có thể là có thể chuyên về nó. Nhưng nó khá bí truyền, vì vậy có lẽ không. Hãy thử nó đi.

GCC 4.7 nói:

$ g++ -std=c++11 test157.cpp 

Nó biên soạn!

Chạy nó:

$ ./a.out 
77 
99 

Nó hoạt động!

Clang 3.1 nói:

$ clang++ -std=c++11 test157.cpp 
test157.cpp:10:8: error: class template partial specialization does not specialize any template argument; to define the primary template, remove the template argument list 
struct Foo<C> 
    ^~~~ 
test157.cpp:9:10: error: too many template parameters in template template parameter redeclaration 
template<template<typename, typename...> class C> 
     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
test157.cpp:3:10: note: previous template template parameter is here 
template<template<typename...> class> 
     ^~~~~~~~~~~~~~~~~~~~~ 
2 errors generated. 

Ai đúng?

Trả lời

7

Clang sai khi từ chối chuyên môn hóa một phần. Để biết làm thế nào để giải thích sai lầm, bạn cần phải hiểu những gì clang chẩn đoán. Nó có nghĩa là để chẩn đoán một chuyên môn từng phần mà các đối số của nó khớp chính xác với danh sách đối số ngầm của mẫu lớp chính (<param1, param2, ... , paramN>).

Tuy nhiên, các danh sách đối số khác nhau nên clang không được chẩn đoán. Đặc biệt điều này không có gì để làm wheter chuyên môn hóa một phần phù hợp với nhiều hoặc ít đối số. Hãy xem xét

template<typename A, typename B> class C; 
template<typename B, typename A> class C<A, B> {}; 

Chuyên môn từng phần ở đây phù hợp với mọi thứ và không phù hợp với mẫu chính. Và các danh sách đối số của cả hai mẫu là khác nhau, do đó, chuyên môn từng phần này là hợp lệ, giống như bạn bè.

+0

Cảm ơn bạn. Ví dụ hấp dẫn. Nghĩ về nó, ví dụ của tôi chỉ là một trường hợp cụ thể của một ví dụ chung về việc chuyên tham số mẫu mẫu biến thể cho bất kỳ số tham số cụ thể nào hơn (ví dụ, hai tham số). Nếu tôi cố gắng để thực hiện một chuyên môn của 'Foo' cho' template class' Tôi nhận được cùng một hành vi: GCC chấp nhận, Clang từ chối. Tôi sẽ gửi một lỗi (nếu nó chưa được thực hiện). Một trích dẫn từ tiêu chuẩn sẽ làm cho tôi hạnh phúc, nếu nó không phải là quá nhiều rắc rối. – glaebhoerl

4
`template<template<typename, typename...> class C> 

không chuyên hơn

template<template<typename...> class> 

Cả hai đều có một danh sách các thông số loại chưa biết. chỉ có một thành viên của danh sách này là một tham số khác. Nó không chứa thông tin bổ sung về loại như vậy mà trình biên dịch nên chọn một trong những khác.

Trong cách sử dụng điển hình của các mẫu variadic, chuyên môn này được tạo theo số lượng tham số. Suy nghĩ về các mẫu variadic như các hàm đệ quy trong thời gian chạy, bạn chỉ nên cung cấp điều kiện kết thúc (như một lớp chỉ lấy một kiểu không xác định).

Clang rất quan tâm đến chẩn đoán vì vậy tôi nghĩ rằng đó là bắt sự bất thường và đúng sai sót. GCC có thể biên dịch nó là lạ. Có thể vì bạn đang chỉ định rõ các mẫu nào sẽ sử dụng trong các cá thể struct Astruct B một cách riêng biệt, gcc có thể nắm bắt được và ngăn chặn sự bất thường đó.

+1

Có sự khác biệt. Một trong số chúng khớp với "các mẫu lớp với số không hoặc nhiều tham số kiểu chữ", các phần tử khác khớp với "các mẫu lớp với một hoặc nhiều tham số tên tệp". Thật vậy, nếu bạn cố gắng chuyển 'template struct A {}' làm đối số mẫu trong đó tham số là kiểu 'template class', cả Clang và GCC sẽ từ chối nó.Tất nhiên điều này không có nghĩa là tiêu chuẩn ngôn ngữ cũng cho phép chuyên môn hóa dựa trên sự khác biệt này. Nếu bạn cung cấp một trích dẫn tôi sẽ rất vui khi được chấp nhận. – glaebhoerl

+0

Đặt một cách khác, nếu có thể chuyên dựa trên số lượng đối số khi chúng ở vị trí dương - 'mẫu ' so với 'mẫu ' - Tôi thấy không có trở ngại về mặt lý thuyết cũng cho phép nó khi chúng ở một vị trí tiêu cực, 'template