C++函数模板:必须使用 & for 参数类型和返回类型?



我正在学习使用函数模板。我发现如果我将参数类型声明为引用,程序将起作用。但是如果参数类型不是引用,我会收到错误。例如:

以下代码打印正确的结果,并且没有错误。

#include <iostream>
using namespace std;
template <typename T>
T & max (T & a, T & b){
return a>b?a:b;
}
int main(int argc, char const *argv[])
{
cout << max(1,2) << endl;
return 0;
}

但是如果我删除代码中的所有"&",即更改上述程序,如下所示:

#include <iostream>
using namespace std;
template <typename T>
T  max (T  a, T  b){
return a>b?a:b;
}
int main(int argc, char const *argv[])
{
cout << max(1,2) << endl;
return 0;
}

此代码将导致以下错误。

a.cpp: In function ‘int main(int, const char**)’:
a.cpp:11:17: error: call of overloaded ‘max(int, int)’ is ambiguous
cout << max(1,2) << endl;
^
a.cpp:5:4: note: candidate: T max(T, T) [with T = int]
T  max (T  a, T  b){
^~~
In file included from /usr/include/c++/7/bits/char_traits.h:39:0,
from /usr/include/c++/7/ios:40,
from /usr/include/c++/7/ostream:38,
from /usr/include/c++/7/iostream:39,
from a.cpp:1:
/usr/include/c++/7/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)

为什么? 谢谢大家对我的帮助!

std 命名空间中已经定义了具有相同(或兼容)名称和参数类型的函数(模板)。

删除

using namespace std;

并在 cout 和 endl 前面加上 std::

std::cout << max(1,2) << std::endl;

否则,您将使用 std 命名空间中的所有名称污染全局命名空间。

第一个示例中不考虑引用参数版本,因为这些常量不符合可修改的左值引用的条件。多亏了不明智的using namespace std;,您正在拉入std版本,这将起作用。您可以在第一个版本中删除您的max代码,它仍然有效,因为一旦这些引用触发取消资格,就不会考虑它。

简而言之,第一个版本不考虑您的max代码,因为它不符合条件,因此使用std::max(确实符合条件)。在第二个版本中,使用 value 参数的代码和使用 const 引用的std::max版本都可以符合条件,因此结果不明确。

有一个模板化的max()函数,它接受命名空间std中的参数(在标准标头<algorithm>中)。 虽然该标准不要求#include <iostream>引入该功能,但它也没有禁止它。 您的标准编译器确实通过<iostream>引入了它。

using 指令 (using namespace std) 使std::max()模板被视为代码中匹配函数的候选者。

在第一个代码示例中,调用max(1,2)std::max()匹配,因为它接受const引用,并且比接受非const引用的函数匹配得更好。 它恰好产生您期望的输出。

在第二个代码示例中,按值传递,编译器没有理由首选您的max()std中的(按值传递或const按引用传递对于传递int文本(如12)同样有效)。 因此,编译器抱怨歧义。

问题是:使用不同的编译器(或其标准库),您的代码可能会以不同的方式失败,因为<iostream>不需要声明std::max(),并且并非所有实现都这样做。

删除 using 指令,代码中std::max()的潜在用法将消失 -std::max()不会被视为任一代码示例中的候选项。 第一个示例将无法编译,因为非const引用不能用于传递文本值。 第二个将编译并生成您期望的输出。 此行为在符合标准的编译器C++编译器之间是一致的(并且不会影响<iostream>等标准标头是否声明std::max())。

最新更新