为什么模板函数调用不明确?

2 c++ templates

#include <iostream>
using namespace std;
template <typename T>
T max(T x, T y)
{
    return (x > y) ? x : y;
}
int main()
{
    cout << max(3, 7) << std::endl;
    cout << max(3.0, 7.0) << std::endl;
    cout << max(3, 7.0) << std::endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我在这里期待 max 的实例

cout << max(3, 7) << std::endl; // max (int, int)
cout << max(3.0, 7.0) << std::endl; // max (double, double)
cout << max(3, 7.0) << std::endl; // max(int, double)
Run Code Online (Sandbox Code Playgroud)

那么问题出在哪里呢?为什么我得到

11 25 [Error] call of overloaded 'max(double, double)' is ambiguous

Bar*_*rry 5

如果您完整地查看编译错误,您就会明白原因。这是 gcc 5.2 给我的:

main.cpp: In function 'int main()':
main.cpp:10:21: error: call of overloaded 'max(int, int)' is ambiguous
     cout << max(3, 7) << std::endl;
                     ^
main.cpp:4:3: note: candidate: T max(T, T) [with T = int]
 T max(T x, T y)
   ^
In file included from /usr/local/include/c++/5.2.0/bits/char_traits.h:39:0,
                 from /usr/local/include/c++/5.2.0/ios:40,
                 from /usr/local/include/c++/5.2.0/ostream:38,
                 from /usr/local/include/c++/5.2.0/iostream:39,
                 from main.cpp:1:
/usr/local/include/c++/5.2.0/bits/stl_algobase.h:219:5: note: candidate: constexpr const _Tp& std::max(const _Tp&, const _Tp&) [with _Tp = int]
     max(const _Tp& __a, const _Tp& __b)
     ^
Run Code Online (Sandbox Code Playgroud)

基本上,有两个max函数 - your 和std::max,它包含在#include来自 的其他 s的某些链中<iostream>。后者是通过查找找到的,因为您

using namespace std;
Run Code Online (Sandbox Code Playgroud)

实际上,我们有:

template <typename T> T max(T, T);                      // yours
template <typename T> T const& max(T const&, T const&); // std
Run Code Online (Sandbox Code Playgroud)

两者并不比另一个更好,因此含糊不清。这是避免using namespace std的一个重要原因。或者在涉及标准库函数时不重新发明轮子的一个重要原因 - 只需使用std::max. 或两者。


另一方面,这个

max(3, 7.0)
Run Code Online (Sandbox Code Playgroud)

无论模板推导失败,都会失败。它将推断Tint第一个参数和第二个T参数double- 但只能有一个T!您必须显式调用max<int>(3, 7.0)ormax<double>(3, 7.0)来避免推导失败,具体取决于您想要转换的两个参数中的哪一个。