为什么模板中的static_assert给出了不同的结果和等价的表达式?

时间:2015-01-09 19:39:10

标签: c++ templates gcc static-assert

我注意到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是正确的?

2 个答案:

答案 0 :(得分:7)

§14.6[temp.res] / p8:

  

如果无法为模板生成有效的专业化,那么   模板没有实例化,模板格式不正确,没有   需要诊断。

在这两种情况下都无法为主要模板生成有效的专业化,因为static_assertD && 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,它将再次依赖,编译器将在解析期间进行评估,从而导致断言始终发生。即使它不是你将要实例化的类。