第326章 引数が複数のコンストラクター

コンストラクターは引数が一つの方が珍しいでしょうから、一応例だけ出しておきたいと思います。

  1 #if defined(__GNUC__) && (__GNUC__ < 7)
  2 #  ifndef __clang__
  3 #    error "gcc is not up to date"
  4 #  endif
  5 #elif defined(__clang__) && (__clang_major__ < 5)
  6 #  error "clang is not up to date"
  7 #endif
  8
  9 #include <type_traits>
 10
 11 template<class T>
 12 struct A {
 13   using value_type = T;
 14   constexpr A(value_type){}
 15   constexpr A(const A&){}
 16   constexpr A& operator=(const A&){}
 17   constexpr A(T,T,int){}
 18   template<class U>
 19   constexpr A(int,T,U){}
 20 };
 21
 22 #if __cplusplus >= 201703L
 23 template<class T>
 24 A(T) -> A<T>;
 25
 26 template<class T>
 27 A(A<T>) -> A<A<T>>;
 28
 29 template<class T>
 30 A(T,T,int) -> A<T>;
 31
 32 template<class U>
 33 A(int,int,U) -> A<int>;
 34
 35 #endif
 36
 37 int main()
 38 {
 39 #if __cplusplus >= 201703L
 40   A a(10);
 41   A b = a;
 42   A c(10,10,'a');
 43   A d('a',10,10);
 44   static_assert(std::is_same<decltype(a),A<int>>::value);
 45   static_assert(std::is_same<decltype(b),A<A<int>>>::value);
 46   static_assert(std::is_same<decltype(c),A<int>>::value);
 47   static_assert(std::is_same<decltype(d),A<int>>::value);
 48 #else
 49   A<int> a(10);
 50   A<int> b = a;
 51   A<int> c(10,10,'a');
 52   A<int> d('a',10,10);
 53   static_assert(std::is_same<decltype(a),A<int>>::value,"");
 54   static_assert(std::is_same<decltype(b),A<int>>::value,"");
 55   static_assert(std::is_same<decltype(c),A<int>>::value,"");
 56   static_assert(std::is_same<decltype(d),A<int>>::value,"");
 57 #endif
 58 }

このソースコードの特徴はクラステンプレート A のテンプレート引数を指定していないところです。

 26 template<class T>
 27 A(A<T>) -> A<A<T>>;
 ...
 40   A a(10);
 41   A b = a;
 ...
 45   static_assert(std::is_same<decltype(b),A<A<int>>>::value);

この例だとコンパイラにとってはわかりにくいので、ガイドを指定してます。

もう一つ注目したいのは推論ガイドの特殊化したりして、コンパイラに明確な指示を送れることです。

 29 template<class T>
 30 A(T,T,int) -> A<T>;
 31
 32 template<class U>
 33 A(int,int,U) -> A<int>;

これがうまくいってるのはアサート文で確認できます。

 42   A c(10,10,'a');
 43   A d('a',10,10);
 ...
 46   static_assert(std::is_same<decltype(c),A<int>>::value);
 47   static_assert(std::is_same<decltype(d),A<int>>::value);

まあこんな感じですが、引数が多い場合にはガイドを書いておくとマニュアル代わりになるかもしれないので、意外に便利かもしれないです。

Copyright 2017-2018, by Masaki Komatsu