プログラミング言語C++において、単一メンバしか含まない共用体(union)を用いるとオブジェクトの明示的な生成/破棄操作が可能となる。貧者(poor man's)のOptional。
#include <iostream> template <typename T> union Wrapper { // 共用体のコンストラクタ/デストラクタ定義は必須 Wrapper() {} ~Wrapper() {} // 明示的なオブジェクト初期化 void init() { new (&obj_) Holder; } // 明示的なオブジェクト廃棄 void destroy() { obj_.~Holder(); } // 制御対象クラス struct Holder { T m_; } obj_; }; struct S { S() { std::cout << "S::ctor\n"; } ~S() { std::cout << "S::dtor\n"; } }; int main() { Wrapper<S> opt; // このタイミングではS型オブジェクトは生成されない std::cout << "call init\n"; opt.init(); // S::S()を呼び出し std::cout << "call destroy\n"; opt.destroy(); // S::~S()を呼び出し }
C++17 12.3/p1, 6より一部引用。
1 In a union, a non-static data member is active if its name refers to an object whose lifetime has begun and has not ended (6.8). At most one of the non-static data members of an object of union type can be active at any time, that is, the value of at most one of the non-static data members can be stored in a union at any time. (snip)
6 [Note: In general, one must use explicit destructor calls and placement new-expression to change the active member of a union. -- end note] [Example: Consider an object
u
of aunion
typeU
having non-static data membersm
of typeM
andn
of typeN
. IfM
has a non-trivial destructor andN
has a non-trivial constructor (for instance, if they declare or inherit virtual functions), the active member of u can be safely switched from m to n using the destructor and placement new-expression as follows:u.m.~M(); new (&u.n) N;-- end example]
関連URL