为什么模板中的 static_assert 使用等效表达式会给我不同的结果?
Why static_assert in template gives me different result with equivalent expressions?
我注意到 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 错误?那么,gcc在什么情况下是正确的呢?
§14.6 [temp.res]/p8:
If no valid specialization can be generated for a template, and that
template is not instantiated, the template is ill-formed, no
diagnostic required.
在这两种情况下,由于 static_assert
(无论 D
的值如何,D && 0
都不会为主模板生成有效的特化。由于不需要诊断,因此编译器可以自由诊断一个(当您使用 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
成员可能是 true
.
的显式特化
所有不是 1、2、3、4 的东西(存在特定的专业化)都将进入 "master" 定义,必须为 D 的每个值断言它将被调用。
因此您需要一个包含 D 且 始终为 false 的表达式,以使编译器对其求值 依赖于D
如果您只使用 0,它将不再依赖,并且编译器将在解析过程中评估它是否匹配,从而导致断言始终发生。即使它不是您要实例化的 class。
我注意到 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 错误?那么,gcc在什么情况下是正确的呢?
§14.6 [temp.res]/p8:
If no valid specialization can be generated for a template, and that template is not instantiated, the template is ill-formed, no diagnostic required.
在这两种情况下,由于 static_assert
(无论 D
的值如何,D && 0
都不会为主模板生成有效的特化。由于不需要诊断,因此编译器可以自由诊断一个(当您使用 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
成员可能是 true
.
所有不是 1、2、3、4 的东西(存在特定的专业化)都将进入 "master" 定义,必须为 D 的每个值断言它将被调用。
因此您需要一个包含 D 且 始终为 false 的表达式,以使编译器对其求值 依赖于D
如果您只使用 0,它将不再依赖,并且编译器将在解析过程中评估它是否匹配,从而导致断言始终发生。即使它不是您要实例化的 class。