看起来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)