で遊んでいましauto
たstd::pair
。以下のコードでf
は、関数はstd::pair
テンプレートパラメータに依存するタイプのを返すことになっています。
実際の例:
例1
template <unsigned S>
auto f()
{
if constexpr (S == 1)
return std::pair{1, 2}; // pair of ints
else if constexpr (S == 2)
return std::pair{1.0, 2.0}; // pair of doubles
else
return std::pair{0.0f, 0.0f}; // pair of floats
}
これは、gcc 9.2、gcc 10.0、clang 9.0およびclang 10.0で動作します。
次に、明確にするために戻り値の型を明示的に記述したいと思いstd::pair
ます。
例2
template <unsigned S>
std::pair<auto, auto> f()
{
if constexpr (S == 1)
return {1, 2};
/* ... */
}
gcc 9.2 / 10.0とclang 9.0 / 10.0はどちらもこれをコンパイルできませんでした。
gcc 9.2
error: invalid use of 'auto'
error: template argument 1 is invalid // first argument (auto) of std::pair
error: template argument 2 is invalid // second argument (auto) of std::pair
error: cannot convert '<brace-enclosed initializer list>' to 'int' in return
最後のエラーメッセージから、gcc 9.2はそれstd::pair<auto, auto>
がであると信じているようint
です。これはどのように説明できますか?
gcc 10.0
error: returning initializer list
このエラーは理解できますが、のコンストラクターstd::pair
が呼び出されることを期待していましたか、それともここに欠けているものがありますか?
clang 9.0および10.0
'auto' not allowed in template argument
excess elements in scalar initializer
no matching function for call to 'f'
わかりました、clangはこれを好きではありません。2番目のエラーメッセージから、clangは戻り値の型もであると考えているようですint
。
最後に、gcc 10.0でコンパイルして取得したエラーを修正するために、std::pair
明示的に返すことにしました。
例3
template <unsigned S>
std::pair<auto, auto> f()
{
if constexpr (S == 1)
return std::pair{1, 2};
/* ... */
}
clang 9.0および10.0
以前と同じですが、以下が追加されています。
no viable conversion from returned value of type 'std::pair<int, int>' to function return type 'int'
ここで、clangは、まだint
?
gcc 9.2
以前と同じです。
gcc 10.0
できます!
いくつかの機能はまだ実装する必要があると思います、または上記の状況の1つで、正しいコンパイラと他の間違ったコンパイラはありますか?私の意見では、例2はうまくいくはずです。それともすべきではないのですか?