看起来Clang(3.8)和GNU C(4.9)中模板实例化的规则是不一样的.这是一个例子:
#include <cstddef> template <bool> class Assert { Assert(); // private constructor for Assert<false> }; template <> class Assert<true> { // implicit public constructor for Assert<true> }; template <size_t N> class A { }; template <class T,size_t N> T foo(A<N>) { return T(N - 1); } template <class T> T foo(A<0>) { // foo is not defined for N=0 Assert<false>(); return T(0); } int main(int argc,char **argv) { foo<int>(A<3>()); return 0; }
这个最小的例子显示了一个模板函数foo,它是在类型T和自然数N上推广的.这个函数没有为N = 0定义,所以我想使用Assert类来表示编译器错误,如果它用这种方式.
这段代码被GNU编译器(以及Visual C 2015)接受,但是Clang给出了“调用Assert类的私有构造函数< false>”的错误.
那么谁是对的?在我看来,没有调用foo< T,0>,所以没有必要实例化这个模板……
编辑:接受Clang对标准的解释,对模板参数实施编译时检查的规范方法是什么?
解决方法
我认为clang是正确的,因为Assert< false>不是依赖类型.
http://en.cppreference.com/w/cpp/language/dependent_name
Non-dependent names are looked up and bound at the point of template definition. This binding holds even if at the point of template instantiation there is a better match:
不要进行无效的专业化.使它们成为通用目的并使用static_assert(带有依赖值)来检查无效的模板参数类型/值. static_assert(std :: is_same< T,int> :: value)或static_assert(N!= 0)