我在c++中做错了什么,泛型函数

What am i doing wrong in this code in C++ , Generic Functions?

本文关键字:泛型 函数 什么 错了 c++ 我在      更新时间:2023-10-16

我在c++中尝试了一个示例泛型函数,代码如下:

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
template <typename T>
T max(T a, T b){
    return (a>b)?a:b;
}
int main()
{
    int a=2,b=4;
    float af = 2.01,bf=2.012;
    double ad = 2.11,bd=1.22;
    cout<<max(a,b);
}

我得到的错误是

main.cpp: In function ‘int main()’:
main.cpp:20:18: error: call of overloaded ‘max(int&, int&)’ is ambiguous
     cout<<max(a,b);
                  ^
main.cpp:20:18: note: candidates are:
main.cpp:9:3: note: T max(T, T) [with T = int]
 T max(T a, T b){
   ^main.cpp: In function ‘int main()’:
main.cpp:20:18: error: call of overloaded ‘max(int&, int&)’ is ambiguous
     cout<<max(a,b);
                  ^
main.cpp:20:18: note: candidates are:
main.cpp:9:3: note: T max(T, T) [with T = int]
 T max(T a, T b){
   ^main.cpp: In function ‘int main()’:
main.cpp:20:18: error: call of overloaded ‘max(int&, int&)’ is ambiguous
     cout<<max(a,b);
                  ^
main.cpp:20:18: note: candidates are:
main.cpp:9:3: note: T max(T, T) [with T = int]
 T max(T a, T b){
   ^

我哪里做错了?
重载max(int&, int&)调用有二义性是什么意思?
为什么我得到它的参数显示为&,而我上面没有定义这样的语法?

问题是c++已经有了一个std::max定义。

再选一个名字,一切都会好起来的。

在c++中,using namespace std方法是一个坏主意,因为将注入数千个名称。只要养成在标准名称前输入std::的习惯就可以了。

还请记住,在编写时节省时间并不是那么重要,重要的是在读取时节省时间(通常代码只编写一次,但阅读和理解多次)。

标准名称前面的

std::实际上加快了阅读速度,并让当场理解正在使用的是标准库的一部分(不是每个人都记住整个标准库)。

Skypjack和6502的答案非常正确,所以我在这里就不详述了。

同样值得注意的是,max的标准版本并没有那么聪明。您可以使用以下代码使其不编译:

int main()
{
  int a = 0;
  double b = 1;
  auto c = std::max(a, b);
}

产生错误消息:

16:错误:没有匹配的函数调用max(int&, double&)

如果我们想重写max,我们可以想象通过这样写来改进它:

#include <type_traits>
namespace notstd {
  template <typename T1, class T2>
  auto max_any(T1 a, T2 b) -> std::common_type_t<T1, T2>
  {
    return (a>b) ? a : b;
  }
}
int main()
{
  int a = 0;
  double b = 1;
  auto c = notstd::max_any(a, b);
}

但是当然会有一些后果。

首先,max_any现在强制获取副本并(可能)执行转换。对于整数和双精度,这几乎不值得一提。

但是,如果T1和T2是具有适当转换操作符的两类对象,则对它们调用max_any可能是一个代价昂贵的操作。它也可能有物质上的副作用。

因此,std::max是根据T&类型的参数定义的。它强制调用者执行转换。事实证明,这不是std::max的限制。这是一个安全功能。

该函数不会在代码中注入任何隐藏的副作用。

为了在其行为中保持"最不意外的路径",标准库有时要求其用户拼写出他们想要的意外行为。

令人惊讶的行为示例

这个程序可以完美地编译:

#include <cstdlib>
#include <iostream>
namespace notstd {
  template <typename T1, class T2>
  auto max_any(T1 a, T2 b)
  {
    return (b < a) ? a : b;
  }
}
struct A {
  A() = default;
};
struct B {
  B() = default;
  B (A const&) { std::exit(100); }
};
bool operator<(B const&, A const &) { return true; }
int main()
{
  A a;
  B b;
  auto c = notstd::max_any(a, b);
  std::cout << "Hello, Worldn";
}

但是它永远不会打印"Hello, World"

维护这段代码的人可能会惊讶地发现。

标准模板库中已经存在一个max函数(即std::max)。
使用using namespace指令,您将std::命名空间导入到您正在使用声明本身的命名空间。
您仍然可以使用以下行来选择max的实现:

cout  <<  ::max(a,b);

否则,正如有人已经提到的,您可以为您的函数选择一个不同的名称,或者直接使用标准模板库中的名称。