我正在尝试使用 c++ 中的模板

I am trying to use templates in c++

本文关键字:c++      更新时间:2023-10-16
#include <iostream>
using namespace std;
template <typename T>
void swap(T& i, T& j)
{
    T temp = i;
    i = j;
    j = temp;
}
int main()
{
    int m = 5, n = 10;
    cout << "Inputs: " << m << "," << n << endl;
    swap(m, n);
    cout << "Outputs: " << m << "," << n << endl;
    return 0;
}

但是,我收到编译错误。有人可以帮助我找到这个问题的解决方案吗?

您的问题是使用命名空间标准。

这是一个完美的例子,说明为什么"使用命名空间 std;"会在您最不期望的时候用误导性和令人困惑的错误消息搞砸您。

从代码中删除"使用命名空间 std",并始终在需要时显式指定"std",即 std::cinstd::cout等。

你需要向自己保证,你再也不会写"使用命名空间 std"了。完全忘记这是C++语言的一部分。

程序的固定版本编译没有任何问题,只需:

#include <iostream>
template <typename T>
void swap(T& i, T& j)
{
    T temp = i;
    i = j;
    j = temp;
}
int main()
{
    int m = 5, n = 10;
    std::cout << "Inputs: " << m << "," << n << std::endl;
    swap(m, n);
    std::cout << "Outputs: " << m << "," << n << std::endl;
    return 0;
}

swap(( 已经是 std 命名空间中定义的函数。将方法重命名为其他名称。

using namespace std;
template <typename T>
void swaper(T& i, T& j)
{
    T temp = i;
    i = j;
    j = temp;
}
int main()
{
    int m = 5, n = 10;
    cout << "Inputs: " << m << "," << n << endl;
    swaper(m, n);
    cout << "Outputs: " << m << "," << n << endl;
    return 0;
}

错误消息清楚地显示:error: call to 'swap' is ambiguous

这是因为swapnamespace std的一部分。
既然你using namespace std; - 这是模棱两可的!

您可以通过以下任一方式解决此问题:

1.删除线路using namespace std;

2.将模板函数重命名为其他名称

实际上,代码中存在许多导致错误消息的问题。 并且由于您的实现(即您正在使用的标准库(而导致问题的一个贡献者。

首先,您已经定义了一个模板化swap(),其形式与名为 swap() 的现有函数相同(通过引用接受两个相同类型的对象(。

其次,using namespace std告诉编译器命名空间std中的名称是代码中匹配名称的候选项。因此,当编译器看到您的代码swap(m,n) mn int的位置时,它会同时看到您的定义和命名空间std中的定义(即 std::swap()作为可行的候选项,以匹配代码中swap()的名称。 两个候选者都能够接受两个类型(引用(int参数,所以编译器没有理由偏爱一个。 因此,它会拒绝您的代码,并显示有关歧义的错误消息。

第三个问题在于您的实现(即您的编译器及其相关的标准库( - <iostream>显然已经绘制了std::swap()的定义。 问题在于,<iostream>既不需要这样做(即,如果您使用不同的编译器构建代码,则不能依赖它发生(,也不需要这样做(即您的代码可以使用某些编译器/库进行编译,但不能使用其他编译器/库(。

实际上,标准要求std::swap()<algorithm>声明,而不是<iostream>

因此,让代码与所有编译器配合使用的选项很简单。 第一种选择是根本不定义自己的swap(),而是依赖标准库。

#include <iostream>
#include <algorithm>   //   Needed to guarantee visibility of std::swap()
using namespace std;
int main()
{
    int m = 5, n = 10;
    cout << "Inputs: " << m << "," << n << endl;
    swap(m, n);
    cout << "Outputs: " << m << "," << n << endl;
    return 0;
}

第二种选择是重命名您的函数,使其不会与std::swap()冲突。

#include <iostream>
using namespace std;
template <typename T>
void your_swap(T& i, T& j)
{
    T temp = i;
    i = j;
    j = temp;
}
int main()
{
    int m = 5, n = 10;
    cout << "Inputs: " << m << "," << n << endl;
    your_swap(m, n);
    cout << "Outputs: " << m << "," << n << endl;
    return 0;
}

第三个选项是从代码中删除using namespace std。 这将使您能够安全地声明自己的swap(),而不会与std::swap()发生冲突。

#include <iostream>
#include <algorithm>
template <typename T>
void swap(T& i, T& j)
{
    T temp = i;
    i = j;
    j = temp;
}
int main()
{
    int m = 5, n = 10;
    std::cout << "Inputs: " << m << "," << n << std::endl;
    swap(m, n);
    std::cout << "Outputs: " << m << "," << n << std::endl;
    return 0;
}

最后一个示例实际上可以很好地编译 - 即使故意使用<algorithm>来绘制std::swap()声明 - 因为编译器没有被告知将std中的名称视为候选名称。 它确实需要为您打算使用的命名空间std(std::coutstd::endl(中的名称添加std::前缀。 如果swap(m,n)被替换为 std::swap(m,n),它也会很好地编译。

第四种选择(我通常在专业编码中更喜欢(是依赖标准库而不是使用using namespace std

#include <iostream>
#include <algorithm>   //   Needed to guarantee visibility of std::swap()
int main()
{
    int m = 5, n = 10;
    std::cout << "Inputs: " << m << "," << n << std::endl;
    std::swap(m, n);
    std::cout << "Outputs: " << m << "," << n << std::endl;
    return 0;
}

我对此选项的偏好的简短解释是,它也避免了各种其他歧义问题。 保存的不必在名称上添加前缀std::的键入不值得在其他歧义问题出现时引起的麻烦。

相关文章:
  • 没有找到相关文章