我想根据参数选择在构造函数中初始化的union成员。以下是一个有效的示例:
struct A {
union {
int i;
float f;
};
A(double d, bool isint) {
if (isint) new(&i) int(d);
else new(&f) float(d);
}
};
当我使用int
和float
时,目标是使用其他更复杂的类型(但在C ++ 14联合中仍然允许),因此使用placement-new (而非作业)。
问题是此构造函数不能为constexpr
,因为constexpr
方法中不允许使用placement-new。有没有办法绕过这个(除了使isint
参数成为正式类型系统的一部分)?某种类型的条件初始化列表可以工作,但我不知道如何做到这一点。
答案 0 :(得分:7)
There is a trick. The key pieces are:
Putting this together, we get:
template<typename T> struct tag {};
struct A {
union {
int i;
float f;
};
constexpr A(tag<int>, double d) : i(d) {}
constexpr A(tag<float>, double d) : f(d) {}
constexpr A(double d, bool isint) : A(isint ? A(tag<int>(), d) : A(tag<float>(), d)) {}
};
constexpr A a(1.0, true); // ok, initializes 'i'
constexpr A b(5, false); // ok, initializes 'f'
This is accepted by recent Clang, GCC, and EDG, and requires only C++11 constexpr
.
Warning: GCC 5.1.0 had a bug where it miscompiled the above code (initializing a
and b
to 0
); this bug is not present in earlier or later versions of GCC.
答案 1 :(得分:1)
对于简单的可构造对象,不需要new
。您可以开始对象生存期,并只需通过赋值运算符选择活动的union
成员。
struct A {
union {
int i;
float f;
};
A(double d, bool isint) {
if (isint) i = d;
else f = d;
}
};
如果会员内部某处有构造函数,那么使用理查德的答案是必要的。