[英]C++14 constexpr union conditional initialization in constructor
我想根據參數選擇在構造函數中初始化的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
參數成為正式類型系統的一部分)? 某種類型的條件初始化列表可以工作,但我不知道有辦法做到這一點。
有一個技巧。 關鍵部分是:
把它們放在一起,我們得到:
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'
這是最近的Clang,GCC和EDG所接受的,並且只需要C ++ 11 constexpr
。
警告: GCC 5.1.0有一個錯誤,它錯誤地編譯了上面的代碼(將a
和b
初始化為0
); GCC的早期版本或更高版本中不存在此錯誤。
對於簡單的可構造對象,不需要new
。 您可以開始對象生存期,並只需通過賦值運算符選擇活動的union
成員。
struct A {
union {
int i;
float f;
};
A(double d, bool isint) {
if (isint) i = d;
else f = d;
}
};
如果成員中某處有構造函數,那么就必須使用Richard的答案。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.