模板的自动返回类型和歧义


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
我认为…....编译器的查看方式是:使用int,您指定typename RT还是typename T1?由于4也是int,也可以是。使用double4直接匹配type double,因此首选第二个重载。
ChrisMM

这对我来说似乎有点狡猾,因为您在返回类型上有点重载,但是使用的模板具有不同数量的参数。
Borgleader

Answers:


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.2转换为int。在第二种情况下,由于显式<int>,返回的结果最初是double,将转换为int
放大器

1
@amplifier:overMax<int>(4, 7.2)在第一种情况下T1=int(提供)T2=double(推导),在第二种情况下RT=int(提供)T1=int, T2=double(推导)。两种方法的内容定义都不用于选择重载。
Jarod42

对我来说,第二种情况是合适的,因为第一种情况有返回类型转换,而第二种情况根本没有转换,不是吗?
放大器

hmmm ...返回类型转换不起作用...那么,是的,从这个角度来看,这两个调用是等效的
放大器
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.