我注意到static_assert
的奇怪行为:
#include <iostream>
template <typename T, unsigned int D> struct Vec
{
static_assert(D && 0, "Invalid dimension for vector!");
};
template <typename T> struct Vec<T, 1> {union {T x, r;};};
template <typename T> struct Vec<T, 2> : Vec<T, 1> {union {T y, g;};};
template <typename T> struct Vec<T, 3> : Vec<T, 2> {union {T z, b;};};
template <typename T> struct Vec<T, 4> : Vec<T, 3> {union {T w, a;};};
int main()
{
Vec<float, 3> v;
v.x = 1;
v.y = 2;
v.z = 3;
return 0;
}
编译好:http://ideone.com/wHbJYP。我希望
static_assert(0, "Invalid dimension for vector!");
给我相同的结果,但它导致静态断言失败:http://ideone.com/UEu9Kv。 两种情况下gcc都正确吗?如果是这样,为什么?或者它是一个gcc bug?那么,在哪种情况下gcc是正确的?
答案 0 :(得分:7)
§14.6[temp.res] / p8:
如果无法为模板生成有效的专业化,那么 模板没有实例化,模板格式不正确,没有 需要诊断。
在这两种情况下都无法为主要模板生成有效的专业化,因为static_assert
(D && 0
永远不会是D
的值)。由于不需要诊断,编译器可以自由诊断一个(当您使用0
时)而不是另一个(当您使用D && 0
时)。
解决方法:
template <unsigned int D> struct always_false : std::false_type {};
template <typename T, unsigned int D> struct Vec
{
static_assert(always_false<D>::value, "Invalid dimension for vector!");
};
编译器在定义时不能再拒绝此操作,因为可能存在always_false
成员为value
的{{1}}的明确专门化。
答案 1 :(得分:0)
一切都不是1,2,3,4(存在特定的专业化)将进入&#34; master&#34;定义,必须为D的每个值断言,它将被调用。
所以你需要一个包含D 并且总是为假的表达式,以使编译器根据D <评估它 / p>
如果您只使用0,它将再次依赖,编译器将在解析期间进行评估,从而导致断言始终发生。即使它不是你将要实例化的类。