クラステンプレートの型推論は一見かなり汎用的に見えますね。
かなり使いずらそうな型の推論、例えばイテレーターも推論はできます。
まずはソースコードから見てみましょう。
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