非常に予期しないオーバーロード解決動作が発生しています。次のコードは、gcc と clang の両方によってあいまいなエラーで拒否されます。
template <typename T>
struct A
{
typedef T key_type;
};
template <typename T>
void foo(A<T> rng, T val);
template <typename T, typename U = T>
void foo(T, typename U::key_type);
int main()
{
A<int> i;
foo(i, 0);
}
エラーは次のとおりです。
test.cpp:16:5: error: call to 'foo' is ambiguous
foo(i, 0);
^~~
test.cpp:8:6: note: candidate function [with T = int]
void foo(A<T> rng, T val);
^
test.cpp:11:6: note: candidate function [with T = A<int>, U = A<int>]
void foo(T, typename U::key_type);
^
どちらも正確に一致すると予想されますが、最初のパラメーターA<T>
ではT
.
私が驚いたのは、2 番目の署名を次のように変更した場合です。
template <typename T, typename U = T>
void foo(T, typename T::key_type);
gcc と clang の両方がコードを受け入れるようになり、最初のオーバーロードを選択するようになりました。
この変更がどのように動作に違いをもたらすかわかりません。明示的に指定も推定もされていない ( U
) テンプレート パラメーターの使用を、そのデフォルト値 ( T
) に置き換えただけです。
繰り返しますが、変更前の動作はそもそも予期しないものであるため、何かが欠けている可能性があります。
誰かが説明できますか:
- 最初のケースがあいまいな理由。と
- なぜ私が行った変更が曖昧さを解決するのですか?
参考までに、私がテストしたコンパイラのバージョンは、gcc 4.8.0 と最近のトランク ビルドの clang です。