简体   繁体   English

我在C ++,Generic Functions中的代码中做错了什么?

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

I was trying out a sample generic function in C++ , the code follows: 我在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);
}

I am getting the error as 我收到的错误是

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){
   ^

What am I doing wrong here ? 我在这做错了什么?
What is meant by call of overloaded max(int&, int&) is ambiguous ? 调用重载max(int&, int&)的含义是不明确的?
Why am I getting its argument shown as & where as there was no such syntax defined by me above ? 为什么我将其参数显示为& where,因为上面没有我定义的语法?

The problem is that C++ already has a std::max definition. 问题是C ++已经有了std::max定义。

Pick another name and everything should be fine. 选择另一个名字,一切都应该没问题。

In C++ the using namespace std approach is a bad idea as thousands of names will be injected. 在C ++中, using namespace std方法是一个坏主意,因为将注入数千个名称。 Just get the habit of typing std:: in front of standard names. 只需养成在标准名称前键入std::的习惯。

Remember also that saving time when writing is not really that important, what is important is saving time when reading (normally code is written just once but read and understood many times). 还要记住,写入时节省时间并不重要,重要的是节省阅读时间(通常只编写一次代码,但多次阅读和理解)。

std:: in front of standard names actually speeds up reading and lets understanding on the spot that what is being used is part of the standard library (not everyone knows the whole standard library by heart). 标准名称前面的std::实际上加快了阅读速度,让现场了解正在使用的是标准库的一部分(不是每个人都清楚地了解整个标准库)。

Skypjack and 6502's answers are spot on so I won't go over that here. Skypjack和6502的答案都是现货,所以我不会在这里讨论。

It is also worth noting that the standard's version of max is not that clever. 值得注意的是,标准版的max并不是那么聪明。 You can cause it not to compile with code like this: 你可以使它不能用这样的代码编译:

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

yields error message: 产生错误消息:

16 : error: no matching function for call to 'max(int&, double&)' 16:错误:没有匹配函数来调用'max(int&,double&)'

If we wanted to rewrite max, we might imagine that we were improving it by writing it this way: 如果我们想重写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);
}

But of course there would be some consequences. 但当然会有一些后果。

Firstly, max_any is now forced to take copies and (possibly) perform conversions. 首先, max_any现在被迫复制并(可能)执行转换。 For integers and doubles this is almost not worth mentioning. 对于整数和双数,这几乎不值得一提。

But if T1 and T2 were two classes of object that had appropriate conversion operators, calling max_any on them could potentially be an expensive operation. 但是如果T1和T2是具有适当转换运算符的两类对象,则在它们上调用max_any可能是一项昂贵的操作。 It might also have material side-effects. 它也可能有重大的副作用。

For this reason, std::max is defined in terms of arguments of type T& . 因此, std::max是根据类型T&的参数定义的。 It forces the caller to perform the conversion. 它强制调用者执行转换。 It turns out that this is not a limitation of std::max . 事实证明,这不是std::max的限制。 It is a safety feature. 这是一个安全功能。

The function does not inject any hidden side-effects into your code. 该函数不会在代码中注入任何隐藏的副作用。

In order to maintain 'the path of least surprise' in its behaviour, the standard library sometimes requires that its users spell out the surprising behaviour that they want. 为了在其行为中保持“最少惊喜的路径”,标准库有时要求其用户说出他们想要的令人惊讶的行为。

Example of surprising behaviour 令人惊讶的行为示例

This program will compile perfectly: 这个程序将完美编译:

#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, World\n";
}

But it will never print "Hello, World". 但它永远不会打印“Hello,World”。

Someone maintaining this code might be surprised to learn that. 维护此代码的人可能会对此感到惊讶。

There exists already a max function in the standard template library (namely std::max ). 标准模板库中已存在max函数(即std::max )。
Using the using namespace directive, you are importing the names from the std:: namespace to the one in which you are using the declaration itself. 使用using namespace指令,您将名称从std:: namespace 导入到您正在使用声明本身的名称。
You can still use the following line to pick your implementation of max : 您仍然可以使用以下行来选择max的实现:

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

Otherwise, as someone already mentioned, you can choose a different name for your function or use directly the one fron the standard template library. 否则,正如已经提到的那样,您可以为函数选择不同的名称,或者直接使用标准模板库中的名称。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM