クラステンプレートの型推論は一見かなり汎用的に見えますね。
かなり使いずらそうな型の推論、例えばイテレーターも推論はできます。
まずはソースコードから見てみましょう。
1 #if __cplusplus < 201703L 2 # pragma message "-std=c++17を指定してください" 3 #endif 4 5 #include <vector> 6 #include <iterator> 7 #include <iostream> 8 9 template<class T> 10 struct container 11 { 12 container( T ){} 13 14 template<class Iter> 15 container(Iter b, Iter e){ 16 std::cout << *b << " " << *std::prev(e) << '\n'; 17 } 18 }; 19 20 #if __cplusplus >= 201703L 21 template<class Iter> 22 container(Iter b, Iter e) 23 -> container<typename std::iterator_traits<Iter>::value_type>; 24 #endif 25 26 int main() { 27 28 std::vector<int> v {2,4}; 29 #if __cplusplus >= 201703L 30 31 # if defined(__clang__) && (__clang_major__ < 6) 32 container c(100); 33 container(v.cbegin(),v.cend()); 34 #else 35 container<int> c(100); 36 container<int>(v.cbegin(),v.cend()); 37 #endif 38 39 #else 40 container<int> c(100); 41 container<int>(v.cbegin(),v.cend()); 42 #endif 43 44 return 0; 45 }
ビルドと実行結果.
$ g++ main.cpp -std=c++17 $ ./a.out 2 4
このコードの目的は構文のチェックです。
まずはカスタムコンテナはイテレーターを指定できるようにします。
9 template<class T> 10 struct container 11 { 12 container( T ){} 13 14 template<class Iter> 15 container(Iter b, Iter e){ 16 std::cout << *b << " " <<*std::prev(e) << '\n'; 17 } 18 };
このクラスは C++17 の推論ガイド( deduction guide )が無い場合にはテンプレート引数を指定しないと使えません。
てなことで推論ガイドをつけてみます。
20 #if __cplusplus >= 201703L 21 template<class Iter> 22 container(Iter b, Iter e) 23 -> container<typename std::iterator_traits<Iter>::value_type>; 24 #endif
これは std::iterator_traits テンプレートを使って Iter ポインターが指すベース型を取得して container のテンプレート引数として設定しています。
Copyright 2017-2018, by Masaki Komatsu