使用模板时C++ "const"神秘重载函数调用

when using templates C++ "const" mystery overloaded function call

本文关键字:const 重载 函数调用 C++      更新时间:2023-10-16

我对下面的代码有一个问题。当我编译它时,它报错如下。现在我的问题是,如果我删除声明中的"const"并将其更改为:

template<class T> T max( T& left, T& right);

就没问题了,编译/执行也正确。为什么编译器认为调用是二义性的?向前声明不应该跟在实现之后吗?

==== start of error message====
max.cpp:10:34: error: call of overloaded ‘max(int, int)’ is ambiguous
max.cpp:10:34: note: candidates are:
max.cpp:5:21: note: T max(const T&, const T&) [with T = int]
/usr/include/c++/4.6/bits/stl_algobase.h:210:5: note: const _Tp& std::max(const _Tp&, const _Tp&) [with _Tp = int]
max.cpp:11:44: error: call of overloaded ‘max(double, double)’ is ambiguous
max.cpp:11:44: note: candidates are:
max.cpp:5:21: note: T max(const T&, const T&) [with T = double]
=======end of error message===

=============代码从这里开始======

#include<iostream>
using namespace std;
template<class T> T max(const T& left, const T& right);
int main(void)
{
      cout<<"max int:"<<  max(1,4)<<endl;
      cout<<"max double:"<<  max(5.02,1.002)<<endl;
}
template<class T>
T max(const T& left, const T& right)
{
      return left > right? left:right;
}

你必须这样做:

  cout<<"max int:"<<  ::max(1,4)<<endl;
  cout<<"max double:"<<  ::max(5.02,1.002)<<endl;

因为在std命名空间中定义了另一个max。您必须通知编译器使用全局命名空间中定义的max,这是您定义的。函数模板Demo

如果您查看std名称空间中定义的std::max:

template <class T> const T& max (const T& a, const T& b);

返回const引用并接受const引用作为形参,这就是为什么当你删除const时,它会编译。

std名称空间已经内置了max,因此您可以不使用using namespace std;行,也可以将max函数放在您自己的名称空间中。

namespace myNamespace {  
    //your max function  
}

在std命名空间中已经定义了几个函数,如max(), swap()和qsort()。所以当你定义自己的函数

max(const T& left,const T& right)

与STD命名空间中的相同,因此出现错误。因此,您可以执行以下操作来使其工作

  1. 使用范围解析运算符::max(x,y)

  2. 调用函数
  3. 从函数中删除const限定符

正如其他人所写的那样,编译器在命名空间std中发现了一个max函数。现在它试图通过函数重载为您获得最佳版本。由于两种签名是相等的,所以不能选择一个最好的版本和投诉。现在,如果删除const,编译器就不能将整型(或双精度)字面值绑定到非const引用。现在它只有一个选择,并使用std::max功能。您可以通过下面的示例看到它:

#include <iostream>
namespace ns1 {
    template<class T>
    void doit(T const&) {
        std::cout << "ns1::doit" << std::endl;
    }
}
template<class T>
void doit(T&) {
    std::cout << "::doit" << std::endl;
}
int main() {
    using namespace ns1;
    int i=1;
    int const j=1;
    doit(1);
    doit(i);
    doit(i+1-1);
    doit(j);
    return 0;
}

因为一切都是int,编译器必须选择非const引用,只有当它有一个非const变量(i)时。在其他情况下,它从命名空间ns1中选择const引用版本。它甚至可以将临时对象绑定到const引用(i+1-1)。max和std::max也是一样。

编辑:

我忘了说如果你在你的声明中删除const编译器选择std::max这当然是正确的,但不是你的