テンプレートの自動戻りタイプとあいまいさ


20

オーバーロードされたテンプレート関数があります:

template<typename T1, typename T2>
auto overMax(T1 a, T2 b)
{
    std::cout << __FUNCSIG__ << std::endl;

    return b < a ? a : b;
}

template<typename RT, typename T1, typename T2>
RT overMax(T1 a, T2 b)
{
    std::cout << __FUNCSIG__ << std::endl;

    return b < a ? a : b;
}

私がそれをこのように呼ぶと:

auto a = overMax(4, 7.2); // uses first template
auto b = overMax<double>(4, 7.2); // uses second template

すべてが完璧に動作しますが、

auto c = overMax<int>(4, 7.2); // error

あいまいな呼び出しを引き起こします。

なぜそれがintでそうなのですか?


4
…....コンパイラがそれを見る方法は、:でinttypename RTまたはを指定していtypename T1ますか?以来4もありint、それはどちらかである可能性があります。しない直接型と一致し、その2番目のオーバーロードが好ましいです。double4double
ChrisMM

これは、戻り値の型のオーバーロードのようなものですが、パラメーターの量が異なるテンプレートを使用しているため、少しおかしな印象を与えます。
ボーグリーダー

回答:


25

RTは推定template<typename T1, typename T2> auto overMax(T1 a, T2 b)できないため、提供しない場合は呼び出すことができます。

テンプレート引数を(部分的に)提供すると、両方の方法が実行可能になります。

しかし、議論によっては、より良い候補になる可能性があります。

  • ために auto b = overMax<double>(4, 7.2); // uses second template

    両方overMax<double, int, double>overMax<double, double>実行可能です。
    ただしoverMax<double, int, double>、完全一致ですが、変換
    overMax<double, double>必要です。intdouble

  • ために auto c = overMax<int>(4, 7.2); // Ambiguous call

    両方overMax<int, int, double>overMax<int, double>実行可能です。
    しかし、どちらも優れた一致でも特別なものでもないため、呼び出しはあいまいです。


なぜどちらもはるかに優れていないのですか?最初のケースではoverMax <int>(4、7.2); 7.2intに変換します。2番目のケースでは、返された結果(最初はdouble)が明示的な<int>のためにintに変換されますか?
増幅器

1
@amplifier:overMax<int>(4, 7.2)最初のケースT1=int(提供)、T2=double(推定)、2番目のケースRT=int(提供)、T1=int, T2=double(推定)になります。両方のメソッドのコンテンツの定義は、オーバーロードの選択には使用されません。
Jarod42

私にとっては、最初のケースには戻り型の変換があり、2番目のケースにはまったく変換がないので、2番目のケースが適していますね。
増幅器

うーん...戻り値の型変換は役割を果たしません...そう、そうです、両方の呼び出しはこの観点から同等です
アンプ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.