static_assert具有部分模板特化

Irf*_*rfy 6 static-assert template-specialization c++11

template<typename T, typename U = void>
struct S { /* static_assert(0, "type unsupported"); */ };
template<typename T>
struct S<T, typename std::enable_if<std::is_integral<T>::value, void>::type> {
    void foo() {}
};
...
S<int> i;
i.foo();
S<double> d;
// d.foo();
Run Code Online (Sandbox Code Playgroud)

我希望"主模板"永远不会被实例化int,但如果我取消注释static_assert,S<int>实例化将失败.即使是单独的typedef S<int> Si;也无法编译.(GCC 4.9.2 Cygwin)

我想要实现的不是S<double>foo()调用时失败,而是在模板本身的实例化中,以及带有意义的错误消息.我知道我可以typename T::nonexistent_type t;在主模板中执行某些操作,这将阻止模板进行编译,但这不如static_assert消息.(注意:将static_assert函数定义放在主模板中仍然无法编译S<int>)

为什么static_assert即使该模板未实例化也会失败?这个标准是强制性的(或者可能是"未指明的")吗?有没有办法以static_assert我想要的方式失败?

Pup*_*ppy 7

static_assert如果您希望它只是实例化时间,则表达式必须依赖于模板参数.这是由标准保证的 - 实现可能(但没有义务)检查static_assertion不依赖于任何模板参数的模板中的s.

你的代码是一种奇怪的迂回方式

template<typename T> struct S {
    static_assert(std::is_integral<T>::value, "type unsupported");
    void foo() {}
};
Run Code Online (Sandbox Code Playgroud)

这清楚地向编译器传达了表达式和模板参数之间的依赖关系,并且更清晰,更易于阅读.我实际上无法弄清楚你是否想要为整数类型或非整数类型的编译失败.