関数について考えてみましょう。
_template<typename T>
void printme(T&& t) {
for (auto i : t)
std::cout << i;
}
_
または、begin()/ end()が有効なタイプの1つのパラメーターを期待するその他の関数。
なぜ次は違法なのですか?
printme({'a', 'b', 'c'});
これらすべてが正当な場合:
_printme(std::vector<char>({'a', 'b', 'c'}));
printme(std::string("abc"));
printme(std::array<char, 3> {'a', 'b', 'c'});
_
これを書くことさえできます:
_const auto il = {'a', 'b', 'c'};
printme(il);
_
または
_printme<std::initializer_list<char>>({'a', 'b', 'c'});
_
テンプレート引数T
を推測できなかったため、最初の行printme({'a', 'b', 'c'})
は不正です。テンプレート引数を明示的に指定すると、機能します。 printme<vector<char>>({'a', 'b', 'c'})
またはprintme<initializer_list<char>>({'a', 'b', 'c'})
。
引数の型が明確に定義されているため、リストした他の引数は正当です。したがって、テンプレート引数T
は問題なく推測できます。
auto
はタイプ_std::initializer_list<char>
_であると見なされるため、il
を含むスニペットも機能します。したがって、printme()
へのテンプレート引数を推測できます。
ここでの唯一の「面白い」部分は、auto
がタイプ_std::initializer_list<char>
_を選択するが、テンプレート引数は選択しないことです。これは、C++ 11標準の§14.8.2.5/ 5が、これがテンプレート引数の非推定コンテキストであると明示的に述べているためです。
関連する引数が初期化子リスト(8.5.4)であるが、パラメーターにstd :: initializer_listがないか、cv修飾されたstd :: initializer_listタイプへの参照がない関数パラメーター。 [例:
_template<class T> void g(T); g({1,2,3}); // error: no argument deduced for T
_—終了例]
ただし、auto
では、§7.1.6.4/ 6は_std::initializer_list<>
_を明示的にサポートしています。
初期化子がbraced-init-list(8.5.4)の場合、_
std::initializer_list<U>
_。
関数をオーバーロードして、initializer_list型の引数を明示的に取得することもできます。
template<typename T>
void printme(std::initializer_list<T> t) {
for (auto i : t)
std::cout << i;
}
これは特に§14.8.2.5/ 5でカバーされています
関連する引数が初期化子リストであるが、パラメーターに
std::initializer_list
がないか、cv修飾された可能性のあるstd::initializer_list
タイプへの参照がない関数パラメーター。 [例:template<class T> void g(T); g({1,2,3}); // error: no argument deduced for T
—例を終了]
これを機能させるために、テンプレート引数タイプを明示的に指定できます。
printme<std::initializer_list<int>>( {1,2,3,4} );