我正在尝试使用 c++ 中的模板
I am trying to use templates in c++
#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::cin
、std::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
。
这是因为swap
是namespace std
的一部分。
既然你using namespace std;
- 这是模棱两可的!
您可以通过以下任一方式解决此问题:
1.删除线路using namespace std;
2.将模板函数重命名为其他名称
实际上,代码中存在许多导致错误消息的问题。 并且由于您的实现(即您正在使用的标准库(而导致问题的一个贡献者。
首先,您已经定义了一个模板化swap()
,其形式与名为 swap()
的现有函数相同(通过引用接受两个相同类型的对象(。
其次,using namespace std
告诉编译器命名空间std
中的名称是代码中匹配名称的候选项。因此,当编译器看到您的代码swap(m,n)
m
和n
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::cout
、std::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::
的键入不值得在其他歧义问题出现时引起的麻烦。
- 没有找到相关文章