【问题标题】:Why Template Function call is ambiguous?为什么模板函数调用不明确?
【发布时间】:2015-09-08 16:42:34
【问题描述】:
#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;
}

我在这里期待 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)

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

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

【问题讨论】:

  • 您应该在不使用using namespace std 的情况下重试,以消除混乱的根源。
  • @juanchopanza 还是一样..
  • 不管怎样做。修复您的代码并发布错误消息。
  • @LetDoit 这与“调用重载的最大值不明确”不一样!
  • @LetDoit 那是因为你们两个需要两个不同的模板参数,因为你使用的是两种不同的类型。

标签: c++ templates


【解决方案1】:

如果您查看完整的编译错误,您就会明白原因。这是 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)
     ^

基本上,有两个 max 函数 - yours 和 std::max,它们包含在来自 &lt;iostream&gt; 的其他 #includes 链中。后者是通过查找找到的,因为您的

using namespace std;

实际上,我们有:

template <typename T> T max(T, T);                      // yours
template <typename T> T const& max(T const&, T const&); // std

两者都不比另一个好,因此模棱两可。这是avoid using namespace std 的一个很好的理由。或者在标准库函数方面不重新发明轮子的一个很好的理由 - 只需使用std::max。或两者。


另一方面,这个

max(3, 7.0)

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

【讨论】:

  • 哪个编译器最好?听说allot关于GCC如何下载和使用?
  • @LetDoit 没有最好的编译器。我刚刚提供了示例输出以表明编译器输出是有价值的。如果你想使用 gcc,你可以 google gcc。
  • @LetDoit 为什么你认为你得到了不正确的输出?这将打印 7 三次。
  • 我期待7.0
  • @LetDoit 期望错误。
【解决方案2】:

线

using namespace std;

肯定会让事情变得复杂。但是,即使您删除了该行,问题仍然存在。

调用max(3, 7.0) 可以解析为max&lt;int&gt;max&lt;double&gt;。要解析为max&lt;int&gt;,必须将double 转换为int。要解析为max&lt;double&gt;,必须将int 转换为double。由于两者都需要转换,并且不能为一个转换赋予比另一个更高的优先级,因此编译器无法确定使用哪一个。

您必须明确要使用哪个版本的max

max&lt;int&gt;(3, 7.0) 会将7.0double 转换为int

max&lt;double&gt;(3, 7.0) 会将3int 转换为double

【讨论】:

    【解决方案3】:

    Max 是一个库函数。只需将函数的最大标识符更改为 max1 或任何其他名称,该名称不是定义任何头文件的函数。 这应该可以解决您的问题。

    【讨论】:

    • 请尝试格式化您的答案,以便清楚地区分代码示例和散文。您可以使用反引号 (`) 将代码括起来。
    猜你喜欢
    • 2014-11-18
    • 1970-01-01
    • 2011-08-27
    • 1970-01-01
    • 2016-05-18
    • 1970-01-01
    • 2020-06-14
    • 1970-01-01
    相关资源
    最近更新 更多