2)「完全な転送コンストラクター」が適切な代替手段になることを妨げる、考えられる技術的な理由はありますか?
ここで、その完全な転送アプローチに関する 1 つの問題を示しました。C++0x ですべてのコンストラクターを転送することです。
また、完全な転送アプローチでは、基本クラスのコンストラクターの明示性を「転送」することはできません。それは常に変換コンストラクターであるか、決してそうではなく、基本クラスは常に直接初期化されます (常にすべてのコンストラクターを使用し、明示的なコンストラクターを使用します)。もの)。
もう 1 つの問題は、イニシャライザ リスト コンストラクタであると推測できませArgs
んinitializer_list<U>
。代わりに、B{args...}
(中括弧に注意してください) を使用してベースに転送し、またはまたはを使用D
してオブジェクトを初期化する必要があります。その場合、初期化子リストの要素の型になり、それらを基本クラスに転送します。その後、イニシャライザ リスト コンストラクタがそれらを受け取ることができます。テンプレート引数パックには、型と長さのさまざまな組み合わせごとに多くの型シーケンスが含まれる可能性があり、初期化構文を選択する必要があるため、これは不要なコードの膨張を引き起こすようです:(a, b, c)
{1, 2, 3}
= {1, 2, 3}
Args
struct MyList {
// initializes by initializer list
MyList(std::initializer_list<Data> list);
// initializes with size copies of def
MyList(std::size_t size, Data def = Data());
};
MyList m{3, 1}; // data: [3, 1]
MyList m(3, 1); // data: [1, 1, 1]
// either you use { args ... } and support initializer lists or
// you use (args...) and won't
struct MyDerivedList : MyList {
template<class ... Args>
MyDerivedList(Args&& ... args) : MyList{ args... } { }
};
MyDerivedList m{3, 1}; // data: [3, 1]
MyDerivedList m(3, 1); // data: [3, 1] (!!)