2012-04-16 17 views
10

比方说,我有这些模板别名:替换失败是否存在依赖于非类型模板参数的错误?

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; 

我可以做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 {}); 
} 

它打印:

是多态的
并不多态

这符合我的期望。

随着铿锵的代码不编译。它会产生以下错误消息。

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. 

它应该编译?这两个编译器中哪一个有问题?

+0

哎呀,我觉得很傻。我有一种感觉,这与模板别名无关,所以标题可能会引起误解:S对不起,我会调查一下并修正标题,如果事实证明这种情况。 – 2012-04-16 19:48:45

+2

'DisableIf > = {}'是否是合法的初始化程序列表初始化?结构可以是模板值参数吗? – jpalecek 2012-04-16 19:49:34

+0

@jpalecek不,结构不能。这就是为什么我使用枚举:) – 2012-04-16 19:51:17

回答

7

首先,感谢@Richard Smith#llvm IRC Channel on oftc的解释。
不幸的是,这是不合法的C++,因此锵是正确的:{}不是一个表达式但支撑,初始化列表并且如需要在一个初始化永远不会成为一个常量表达非类型模板参数。

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

用于非类型,非模板模板参数A 模板参数应是以下之一:用于非类型模板 -

  • 参数的积分或枚举类型,转换的常量表达式(5.19)的类型模板电子参数;或
  • [...]

一个解决方案是在enabler虚值。

+2

这不是一个好的论点 - 我们在这里没有谈论模板参数(没有人试图例如'f '),但是默认参数具有参数声明的语法,原则上可以有' }'在rhs上(如果'enabler {}'是一个常量表达式,或者'x',给定'enabler x {}',常量就不会有问题)。但是,8.3.6/3表示在模板参数声明的情况下应该有一个表达式。 – jpalecek 2012-04-16 22:40:07

+0

@jpalecek:“oone试图例如'f '”呃,调用'f '确实*那*。 – GManNickG 2012-04-16 23:52:43

+1

@GManNickG:不,它没有。默认参数没有被指定(至少显式)为文本替换。 – jpalecek 2012-04-18 15:35:32

相关问题