我何时需要指定模板类型

时间:2016-06-03 06:41:59

标签: c++ templates function-templates

我写了一个简单的模板来查找参数列表中的最小数字。

template<typename T>
T smallerList(T a, T b) {
    std::cout << "a= " << a << " b= " << b << std::endl;
    return a < b ? a : b;
}

template<typename T, typename... Rest>
T smallerList(const T& param0, const Rest&... rest) {
    T temp =  smallerList(rest...);
    return param0 < temp ? param0 : temp;
}

int main()
{
       // Works, returns "3"
       std::cout << "Smaller: " << smallerList(4, 5, 6, 3, 7) << std::endl;

       // Sort of works, returns "2". Should be "2.14".
       std::cout << "Smaller: " << smallerList(3.14, 43534, 100.2, 3.13, 2.14) << std::endl; 

}

由于某种原因,第二个函数调用返回2而不是2.14。为什么会这样?

我已经打印了变量的中间值,它们是正确的。当smallList返回时,似乎发生了隐式转换。

我能够通过更改行来解决这个问题

T temp =  smallerList(rest...);

T temp =  smallerList<T>(rest...);

此更改后,该功能按预期打印2.14。

我的问题:为什么我需要指定类型?我认为模板函数是为每个被调用的类型“创建”的吗?

1 个答案:

答案 0 :(得分:2)

好的,我不知道如何真正帮助你,因为我不知道你想拥有什么样的逻辑。但是在你的变量模板中你允许类型混合,并且在你的第二个向量中,你传递一个整数 - 43534,所以当递归回滚时2.14向后传播你会得到像

这样的东西

return (int)(43534 < 2.14? 43534 : 2.14);

因为43534将是param0,并且您返回param0类型,2.14会转换为2。接下来它会转换回float但你却看不到它。

您需要检查参数的类型是否相同,或者提出一些逻辑来推广您的参数。并不是说如果你使用43534.0它会像你期望的那样工作,因为它不再是int

编辑:

T temp = smallerList<T>(rest...);这对你没有帮助,它会改变行为,迫使每个参数的强制转换为第一个参数的类型。好吧它变得更加一致。但试试:

smallerList(7, 10.5, 10, 3.13, 2.14)

它会破裂。我不是百分百肯定为什么,但我想它不能匹配递归结束,因为它会寻找smallerList(int, float)并且您的终结器模板不会匹配。

您需要以下内容:

template<typename T, typename U>
T smallerList(T a, U b) {
    std::cout << "a= " << a << " b= " << b << std::endl;
    return a < b ? a : b;
}

它也会丢弃第二种类型,因此您将进行类型转换,但如果您的目标是保持第一个参数的类型,则它是一致的。