私はstd::make_unique
を使用して、コンストラクタがstd::initializer_list
を受け取るクラスをインスタンス化しようとしています。ここでは最小限のケース:
#include <string>
#include <vector>
#include <initializer_list>
#include <memory>
struct Foo {
Foo(std::initializer_list<std::string> strings) : strings(strings) {}
std::vector<std::string> strings;
};
int main(int, char**) {
auto ptr = std::make_unique<Foo>({"Hello", "World"});
return 0;
}
Colir でビルドできないことがわかります:
main.cpp:14:56: error: no matching function for call to 'make_unique(<brace-enclosed initializer list>)'
auto ptr = std::make_unique<Foo>({"Hello", "World"});
では、make_unique
はinitializer_list
sを使用できないと報告されていますか? GCC 4.9.1にバグはありますか?または私は何かを見落としましたか?
_std::make_unique
_は、オブジェクトコンストラクターに渡される引数の型を推定する関数テンプレートです。残念ながら、括弧で囲まれたリストは(auto
宣言を除いて)推定できません。そのため、不足しているパラメーターの型の場合、関数テンプレートをインスタンス化できません。
_std::make_unique
_を使用することはできませんが、そのルートは使用しないでください。子供のために、可能な限りネイキッドnew
sを使用しないでください。または、型を指定して型の推論を機能させることができます。
std::make_unique<Foo>(std::initializer_list<std::string>({"Hello", "World"}))
std::make_unique<Foo, std::initializer_list<std::string>>({"Hello", "World"})
auto il = { "Hello"s, "World"s }; auto ptr = std::make_unique<Foo>(il);
最後のオプションはauto
宣言に特別なルールを使用します。これは(上記で示唆したように)do実際に_std::initializer_list
_を導き出します。
いくつか追加の文字を入力する準備ができている場合は、これを行うことができます。
auto ptr = std::make_unique<Foo>( make_init_list( { "Hello"s , "World"s } ));
ここで、init_list
は次のように定義されています
template<typename T>
std:: initializer_list<T> make_init_list ( std:: initializer_list<T> && l ) {
return l;
}
これにより、控除を行うことができ、これを行う必要のあるコードに多くの場所がある場合に便利です。
(clang 3.9とgcc 6.2.0で動作します。std::string
- literalを微調整してmake_shared
に変更する必要があったことを除いて、g ++-4.8.4でも動作するようになりました。ただし、 make_init_list
内のT
は問題なく動作しました。)
実際、これは拡張機能ですか? make_init_list
の控除の成功は、規格で要求されているかどうか?