2012-04-16 8 views
10

Hãy nói rằng tôi có những mẫu bí danh:Lỗi thay thế có phải là lỗi với các tham số mẫu không phụ thuộc không?

enum class enabler {}; 

template <typename T> 
using EnableIf = typename std::enable_if<T::value, enabler>::type; 
template <typename T> 
using DisableIf = typename std::enable_if<!T::value, enabler>::type; 

tôi có thể làm như sau trong GCC:

#include <iostream> 

template <typename T, EnableIf<std::is_polymorphic<T>> = {}> 
void f(T) { std::cout << "is polymorphic\n"; } 

template <typename T, DisableIf<std::is_polymorphic<T>> = {}> 
void f(T) { std::cout << "is not polymorphic\n"; } 

struct foo { virtual void g() {} }; 

int main() { 
    f(foo {}); 
    f(int {}); 
} 

It in:

là đa hình
không phải là đa hình

Điều phù hợp với mong đợi của tôi.

Với mật mã không biên dịch. Nó tạo ra các thông báo lỗi sau.

test.cpp:11:58: error: expected expression 
template <typename T, EnableIf<std::is_polymorphic<T>> = {}> 
                 ^
test.cpp:14:59: error: expected expression 
template <typename T, DisableIf<std::is_polymorphic<T>> = {}> 
                 ^
test.cpp:20:3: error: no matching function for call to 'f' 
    f(foo {}); 
^
test.cpp:12:6: note: candidate template ignored: couldn't infer template argument '' 
void f(T) { std::cout << "is polymorphic\n"; } 
    ^
test.cpp:15:6: note: candidate template ignored: couldn't infer template argument '' 
void f(T) { std::cout << "is not polymorphic\n"; } 
    ^
test.cpp:21:3: error: no matching function for call to 'f' 
    f(int {}); 
^
test.cpp:12:6: note: candidate template ignored: couldn't infer template argument '' 
void f(T) { std::cout << "is polymorphic\n"; } 
    ^
test.cpp:15:6: note: candidate template ignored: couldn't infer template argument '' 
void f(T) { std::cout << "is not polymorphic\n"; } 
    ^
4 errors generated. 

Nó có nên biên dịch không? Trình biên dịch nào trong số hai trình biên dịch bị lỗi?

+0

Rất tiếc, tôi cảm thấy ngớ ngẩn. Tôi có cảm giác điều này không liên quan gì đến bí danh mẫu, vì vậy tiêu đề có thể gây hiểu nhầm: S Xin lỗi về điều đó, tôi sẽ điều tra một chút và sửa tiêu đề nếu điều đó xảy ra. –

+2

'DisableIf > = {}' là khởi tạo danh sách khởi tạo hợp pháp chưa? Cấu trúc có thể là các tham số giá trị mẫu không? – jpalecek

+0

@jpalecek Không, cấu trúc không thể. Đó là lý do tại sao tôi sử dụng một enum :) –

Trả lời

7

Đầu tiên và trên hết, nhờ @Richard Smith trên số #llvm IRC Channel on oftc để giải thích.
Thật không may, đây là không hợp pháp C++ và như vậy Clang là đúng: {} không phải là một biểu hiện nhưng một chuẩn bị tinh thần-init-list và như vậy sẽ không bao giờ là một hằng số biểu như là cần thiết trong initializer của một tham số mẫu không phải kiểu.

§14.3.2 [temp.arg.non-type] p1

Một mẫu đối số cho một tổ chức phi loại, phi mẫu mẫu tham số sẽ là một trong:

  • cho một template- không loại tham số loại tích phân hoặc kiểu liệt kê, biểu thức hằng số được chuyển đổi (5.19) của loại templat thông số điện tử; hoặc
  • [...]

Một giải pháp sẽ là một giá trị dummy trong enabler.

+2

Đó không phải là một đối số tốt - chúng ta không nói về các đối số mẫu ở đây (ví dụ, không có ví dụ 'f '), nhưng đối số mặc định, có cú pháp khai báo tham số, về nguyên tắc có '{ } 'trên rhs (và nếu' enabler {} 'là một biểu thức không đổi, hoặc' x', được đưa ra 'enabler x {}', không có vấn đề gì với hằng số). Tuy nhiên, 8.3.6/3 nói rằng cần có một biểu thức trong trường hợp khai báo tham số mẫu. – jpalecek

+0

@jpalecek: "không cố gắng ví dụ.' F '" Uh, gọi 'f ' không * chính xác * điều đó. – GManNickG

+1

@GManNickG: Không, không. Các tham số mặc định không được chỉ định (ít nhất là một cách rõ ràng) như là các thay thế văn bản. – jpalecek