【问题标题】:C++ function template: Must use & for argument type and return type?C++ 函数模板:必须使用 & 作为参数类型和返回类型?
【发布时间】:2017-11-04 07:59:18
【问题描述】:

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

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

#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;
}

但是如果我把代码中的“&amp;”全部去掉,也就是把上面的程序改成如下:

#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)

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

【问题讨论】:

  • 编译器告诉你:你对 max 的调用是模棱两可的,我想是因为 std 命名空间中有 max 模板
  • 不使用using namespace std;的另一个理由
  • 第一个示例无效,您没有使用模板。

标签: c++ function templates


【解决方案1】:

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

删除

using namespace std;

并在 cout 和 endl 前加上 std::

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

否则,您的全局命名空间已被 std 命名空间中的所有名称污染。

【讨论】:

    【解决方案2】:

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

    简而言之,第一个版本不考虑您的 max 代码,因为它不符合条件,因此使用 std::max 代替(确实符合条件)。在第二个版本中,您使用值参数的代码和使用 const-references 的 std::max 版本都可以限定,因此会产生歧义。

    【讨论】:

      【解决方案3】:

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

      using 指令 ​​(using namespace std) 导致 std::max() 模板被视为代码中匹配函数的候选对象。

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

      在您的第二个代码示例中,按值传递,编译器没有理由更喜欢您的 max()std 中的那个(按值传递或通过 const 引用传递对于传递int 类似 12 的字面量)。因此编译器抱怨歧义。

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

      删除 using 指令,std::max() 在您的代码中的潜在用法将消失 - std::max() 在您的任何一个代码示例中都不会被视为候选对象。您的第一个示例将无法编译,因为非const 引用不能用于传递文字值。第二个将编译并产生您期望的输出。这种行为将在符合标准的 C++ 编译器之间保持一致(并且不会影响像 &lt;iostream&gt; 这样的标准头文件是否声明 std::max())。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-04-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-07-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多