クラスのネストは良くあることですが 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