第324章 ガイドなしの型推論

C++17 の推論ガイドの構文はあると良い程度で実際はかなり多くの型推論でガイドは不要です。

例えば以下のようなクラステンプレートにガイドは不要です。

  1 #if __cplusplus < 201703L
  2 # pragma message "cpp version is old! try -std=c++17 "
  3 #endif
  4
  5 #if defined(__GNUC__) && (__GNUC__ < 7)
  6 #  ifndef __clang__
  7 #    pragma message "GCCのバージョンが古いです…"
  8 #  endif
  9 #elif not defined(__clang__) && (__clang_major__ > 5)
 10 #  pragma message "Clangのバージョンが古いです"
 11 #endif
 12
 13 #include <type_traits>
 14
 15 template<class T>
 16 struct A
 17 {
 18   template<class U>
 19   static constexpr bool B = U();
 20
 21   template<class U,bool V = B<U>>
 22   A(T,U){}
 23 };
 24
 25 int main()
 26 {
 27 #if __cplusplus >= 201703L
 28   A a(1,2);
 29   static_assert(std::is_same_v<decltype(a),A<int>>);
 30 #else
 31   A<int> a(1,2);
 32   static_assert(std::is_same<decltype(a),A<int>>::value,"");
 33 #endif
 34 }

このコードは static_assert での構文チェックだけをしているので、ビルドしても出力はありません。

クラステンプレート A のコンストラクターの呼び出しで型推論が行われていますね。

 15 template<class T>
 16 struct A
 17 {
 18   template<class U>
 19   static constexpr bool B = U();
 20
 21   template<class U,bool V = B<U>>
 22   A(T,U){}
 23 };

このコンストラクターは中々曲者ですが、後述する多重ネストがなければ、あっさり推論をしてくれます。

 27 #if __cplusplus >= 201703L
 28   A a(1,2);
 29   static_assert(std::is_same_v<decltype(a),A<int>>);

とは言え C++17 を使わないのであれば従来の構文が必要となってきます。

 30 #else
 31   A<int> a(1,2);
 32   static_assert(std::is_same<decltype(a),A<int>>::value,"");
 33 #endif

テンプレート引数はコード内のドキュメントとしても機能することがあるので、推論なしもありと言えばありですかね。

Copyright 2017-2018, by Masaki Komatsu