为什么编译器在这里抱怨函数歧义
Why does the compiler complain about function ambiguity here?
我正在尝试运行"加速C++"(A. Koenig, B. Moo)(§8.2.2)一书中的一些示例代码:
#include <iostream>
#include <vector>
using std::cout;
using std::endl;
using std::vector;
template <class In, class X>
In find(In begin, In end, const X &x)
{
while (begin != end && *begin != x) {
++begin;
}
return begin;
}
int main()
{
vector<int> v;
v.push_back(5);
v.push_back(32);
v.push_back(42);
v.push_back(7);
cout << *find(v.begin(), v.end(), 42) << endl;
return 0;
}
find
函数在书中是这样的;我自己写的main
函数。
clang++ 和 g++ 都不会编译它。似乎他们在抱怨我的find
功能引入了std::find
的歧义。但是,我从未在代码中使用过using namespace::std;
或using std::find;
,因此如果包含编译器,甚至不应该允许编译器使用std::find
。这是怎么回事?
我想你已经绊倒了"Koenig查找"(是的,同一个Koenig,所以你会认为他会发现问题),又名"ADL"。
假设通过间接包含,<algorithm>
已被拉入。
如果std::vector<int>::iterator
(参数的类型)是命名空间 std
中的一个类,则std::find
是调用的匹配项,即使您从未"使用"过它,因此调用是不明确的。
如果std::vector<int>::iterator
是int*
,则std::find
不是候选者,并且调用不是模棱两可的。
无论哪种方式都是std::vector
的有效实现,并且无论<iostream>
或<vector>
是否包含<algorithm>
,它都是实现定义的。因此,您的代码不可移植,但实现几乎无法诊断可移植性问题,除非代码在该实现上实际失败。
在更典型的 ADL 情况下,关联命名空间中的函数或函数模板比调用方驻留或"使用"的命名空间中的函数或函数模板更好(更具体),因此避免了歧义。但是您的全局find
与std::find
基本相同,因此不适用。
http://ideone.com/Cskur:
#include <iostream>
namespace foo {
struct Foo {};
/* same as the one we'll define later */
template <typename T>
void func(T) {
std::cout << "namespace function templaten";
}
/* this would be a better match
void func(Foo) {
std::cout << "namespace functionn";
}
*/
}
template <typename T>
void func(T) {
std::cout << "global function templaten";
}
int main() {
foo::Foo f;
func(f);
}
结果:
prog.cpp:19: error: call of overloaded ‘func(foo::Foo&)’ is ambiguous
结论:使用来自std
的名称有些危险,即使在其他命名空间中也是如此。
或者,如果您愿意:从其他命名空间中的std
定义名称可能意味着调用方需要小心。区别主要在于谁在错误发生时修复错误。
- 我知道函数调用中存在歧义.有没有办法调用foo()函数
- 数组初始值设定项的构造函数歧义
- 为什么下面带有非常量转换函数的代码没有歧义?
- std::bind 是否实现了 std::ref 和 std::cref 来消除函数调用的歧义?
- 使用 bool 和 const char 重载的 C++ 函数会在没有警告的情况下产生歧义 (MSVC2012)
- C++SFINAE enable_if_t成员函数,如何消除歧义?
- 当存在覆盖歧义函数时,代码如何运行?
- 如何区分宏函数和函数函数而没有任何歧义?
- 模板与常规函数歧义 - UB?
- C++ 类的构造函数和函数调用运算符 () 重载之间的歧义
- 如何解决传递给boost线程的函数中的歧义
- 如何让编译器知道要调用函数的哪个重载以避免歧义?
- 关于模板化函数上传递的右值引用和传递的参数的歧义
- C++ 显式多参数构造函数歧义
- 减少模板化变差函数歧义的最佳方法是什么
- 重载模板化函数歧义问题
- 为什么编译器在这里抱怨函数歧义
- C++多重继承+虚拟函数(-歧义)=怪异行为(也是函数指针)
- 虚函数歧义求解
- 转换运算符重载 - 函数歧义