2つのテンプレートを宣言します。1つ目は引数x
をタイプT
からタイプU
に変換し、2つ目はタイプU
からタイプT
に変換します。 10でcast
を呼び出すと、コンパイラは文句を言いません。どちらも使用する要件を満たしているので、あいまいさがあるはずですが、本当ですか?このコードは10を出力します。
#include <iostream>
template<typename T, typename U>
U cast(T x) {
return static_cast<U>(x);
}
template<typename T, typename U>
T cast(U x) {
return static_cast<T>(x);
}
int main() {
std::cout << cast<int,float>(10) << '\n';
}
cast<int, float>
を使用すると、両方のテンプレートが考慮されます。
template<typename T=int,typename U=float>
U cast(T x);
template<typename T=int,typename U=float>
T cast(U x);
次に、次のように置き換えます。
template<typename T=int,typename U=float>
float cast(int x);
template<typename T=int,typename U=float>
int cast(float x);
現時点では、推測できるタイプはありません。そこで、過負荷の解決に進みます。
1つのケースでは、callingキャストのときにint
を取得してfloat
に変換でき、もう1つのケースではint
を取得して変換します。 int
when calling cast。キャストのbodyをまったく調べていないことに注意してください。ボディは過負荷の解決には関係ありません。
2番目の非変換(呼び出しの時点)はより適切に一致するため、過負荷が選択されます。
これを行った場合:
std::cout << cast<int>(10) << "\n";
物事はより面白くなります:
template<typename T=int,typename U=?>
U cast(T x);
template<typename T=int,typename U=?>
T cast(U x);
最初のものについては、U
を推測することはできません。 2つ目はできます。
template<typename T=int,typename U=?>
U cast(int x);
template<typename T=int,typename U=int>
int cast(int x);
したがって、ここでは実行可能なオーバーロードが1つあり、それが使用されます。
関数の引数が最初のテンプレートパラメータと完全に一致するため、インスタンス化はあいまいではありません。リテラル10
はint
であり、これも最初のテンプレートタイプに明示的に指定されます。
引数の型が明示的に指定された型と一致しない場合(したがって、変換が必要)、インスタンス化をあいまいにすることができます。
// error: call of overloaded 'cast<int, float>(unsigned int)' is ambiguous
std::cout << cast<int,float>(10u) << "\n";