触发union的非活动成员的lvalue-to-rvalue转换不是常量表达式。也就是说,给定union
:
template<class T, class U>
union A {
constexpr A(T t) : t_{t} {}
constexpr A(U u) : u_{u} {}
T t_;
U u_;
};
和constexpr
函数foo
:
template<class T, class U>
constexpr auto foo() {
A<T, U> a(T{});
return a.u_;
}
以下计划:
int main() {
constexpr auto test = foo<int, double>();
return 0;
}
失败并显示错误消息:
error: constexpr variable 'test' must be initialized by a
constant expression
constexpr auto test = foo<int, double>();
^ ~~~~~~~~~~~~~~~~~~
note: read of member 'u_' of union with active member 't_' is
not allowed in a constant expression
return a.u_;
^
note: in call to 'foo()'
constexpr auto test = foo<int, double>();
^
1 error generated.
在C ++ 14中的常量表达式中是否有解决方法来实现此行为? reinterpret_cast
也不允许。
动机:我试图制作google-test的浮点比较实用程序constexpr。
答案 0 :(得分:4)
不,在C ++ 14中,没有办法在常量表达式中进行类型惩罚。除了常数表达式之外,没有办法做到这一点;您展示的代码在运行时将具有未定义的行为。
作为一般情况下不允许这样做的一个例子,请考虑一下:
union U { int *p; size_t n; };
int a;
constexpr U u = { &a };
static_assert(u.n != 0x400e158, "'a' is at my favourite address");
如果允许这样做,则需要在编译期间确定a
的运行时地址。