C++11で導入されたリスト初期化(list initialization)構文で用いられるstd::initializer_list<E>
では、要素型E
にコピー操作を要求するため*1、std::unique_ptr
などのコピー不可/ムーブのみ可能な(Move-only)型を扱えない。この制限により Move-only 型の標準コンテナ初期化ではリスト初期化を利用できず、メンバ関数push_back
やemplace_back
で1要素づつ追加する必要がある。
本記事の内容はStack Overflowで見つけた質問と回答に基づく。
std::vector<std::unique_ptr<int>> vec0 = { std::make_unique<int>(1), std::make_unique<int>(2), std::make_unique<int>(3) }; // NG: ill-formed // コピーコンストラクタunique_ptr(const unique_ptr&)が選択されるが // Move-only型では同オーバーロードはdelete宣言されている。 std::vector<std::unique_ptr<int>> vec1; vec.push_back(std::make_unique<int>(1)); // OK vec.push_back(std::make_unique<int>(2)); // OK vec.emplace_back(new int(3)); // OKだが... unique_ptrには例外安全性の観点から非推奨
C++11 8.5.4/p5-6より引用(下線部は強調)。
5 An object of type
std::initializer_list<E>
is constructed from an initializer list as if the implementation allocated an array of N elements of typeE
, where N is the number of elements in the initializer list. Each element of that array is copy-initialized with the corresponding element of the initializer list, and thestd::initializer_list<E>
object is constructed to refer to that array. If a narrowing conversion is required to initialize any of the elements, the program is ill-formed. [Example:struct X { X(std::initializer_list<double> v); }; X x{ 1,2,3 };The initialization will be implemented in a way roughly equivalent to this:
double __a[3] = {double{1}, double{2}, double{3}}; X x(std::initializer_list<double>(__a, __a+3));assuming that the implementation can construct an
initializer_list
object with a pair of pointers. -- end example]
6 The lifetime of the array is the same as that of theinitializer_list
object. [Example:typedef std::complex<double> cmplx; std::vector<cmplx> v1 = { 1, 2, 3 }; void f() { std::vector<cmplx> v2{ 1, 2, 3 }; std::initializer_list<int> i3 = { 1, 2, 3 }; }For
v1
andv2
, theinitializer_list
object and array created for{ 1, 2, 3 }
have full-expression lifetime. Fori3
, theinitializer_list
object and array have automatic lifetime. -- end example] [Note: The implementation is free to allocate the array in read-only memory if an explicit array with the same initializer could be so allocated. -- end note]
関連URL