## クラステンプレートのコンストラクターからの実引数推定 C++17ではクラステンプレートのコンストラクターの実引数からテンプレート実引数の推定が行えるようになった。 ~~~cpp template < typename T > struct X { X( T t ) { } } ; int main() { X x1(0) ; // X X x2(0.0) ; // X X x3("hello") ; // X } ~~~ これは関数テンプレートが実引数からテンプレート実引数の推定が行えるのと同じだ。 ~~~cpp template < typename T > void f( T t ) { } int main() { f( 0 ) ; // f f( 0.0 ) ; // f f( "hello" ) ; // f } ~~~ ### 実引数ガイド クラステンプレートのコンストラクターからの実引数は便利だが、クラスのコンストラクターはクラステンプレートのテンプレートパラメーターに一致しない場合もある。そのような場合はそのままでは実引数推定ができない。 ~~~cpp // コンテナー風のクラス template < typename T > class Container { std::vector c ; public : // 初期化にイテレーターのペアを取る。 // IteratorはTではない。 // Tは推定できない template < typename Iterator > Container( Iterator first, Iterator last ) : c( first, last ) { } } ; int main() { int a[] = { 1,2,3,4,5 } ; // エラー // Tを推定できない Container c( std::begin(a), std::end(a) ) ; } ~~~ このため、C++17には推定ガイドという機能が提供されている。 ~~~c++ テンプレート名( 引数リスト ) -> テンプレートid ; ~~~ これを使うと、以下のように書ける。 ~~~c++ template < typename Iterator > Container( Iterator, Iterator ) -> Container< typename std::iterator_traits< Iterator >::value_type > ; ~~~ C++コンパイラーはこの推定ガイドを使って、Container\::Container(Iterator, Iterator)からは、Tをstd::iterator_traits\::value_typeとして推定すればいいのだと判断できる。 例えば、初期化リストに対応するには以下のように書く。 ~~~cpp template < typename T > class Container { std::vector c ; public : Container( std::initializer_list init ) : c( init ) { } } ; template < typename T > Container( std::initializer_list ) -> Container ; int main() { Container c = { 1,2,3,4,5 } ; } ~~~ C++コンパイラーはこの推定ガイドから、Container\::Container( std::initializer_list\ )の場合はTをTとして推定すればよいことがわかる。 機能テストマクロは__cpp_deduction_guides, 値は201606。