第325章 ネストの推論

クラスのネストは良くあることですが 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 #endif
 10
 11 #include <type_traits>
 12
 13 template<typename T>
 14 struct Foo
 15 {
 16   template<class U>
 17   Foo(T,U){}
 18 };
 19
 20 template<class T>
 21 struct Bar1
 22 {
 23   template<class U>
 24   struct Bar2
 25   {
 26     explicit Bar2(T,U,int){}
 27   };
 28 #if (__cplusplus >= 201703L) && defined(__clang__) && (__clang_major__ > 5)
 29   template<class U>
 30   Bar2(T,U,int) -> Bar2<U>;
 31 #endif
 32 };
 33
 34 int main() {
 35 #if __cplusplus >= 201703L
 36   Foo foo(100,1.0);
 37 #else
 38   Foo<int> foo(100,1.0);
 39 #endif
 40
 41   Bar1<int>::Bar2 bar(1,'a',1);
 42   static_assert(std::is_same<decltype(bar),Bar1<int>::Bar2<char>>::value,"");
 43   return 0;
 44 }

この中でネストがわかりやすい箇所です。

 13 template<typename T>
 14 struct Foo
 15 {
 16   template<class U>
 17   Foo(T,U){}
 18 };

インスタンスを作る際、以下のようにテンプレート引数指定はいらないです。

 35 #if __cplusplus >= 201703L
 36   Foo foo(100,1.0);
 37 #else

このようにネストの型推論もできるっちゃできるんですが GCC と CLANG の実装に誤差があるらしいです。

残りのコードでお見せしたかったのは GCC で以下の構文がエラーではじかれる点です。

 28 #if (__cplusplus >= 201703L) && defined(__clang__) && (__clang_major__ > 5)
 29   template<class U>
 30   Bar2(T,U,int) -> Bar2<U>;
 31 #endif

ま GCC でも推論はできてるので、どうでもいいっちゃあどうでも良いですがね…

 (´・ω・`)

筆者は標準規格からは程遠いのでヘッダー等を見てあまり気にならなければ、特に深入りはしないスタンスですからね。

この件は GCC が誤っていて CLANG が正しいという意見もあるみたいですね。

Copyright 2017-2018, by Masaki Komatsu