【发布时间】:2012-09-26 17:24:49
【问题描述】:
我有两个用于 ADL 的 sn-ps 用于演示目的。两个 sn-ps 都被 VC10、gcc 和 comeau C++ 编译器编译过,结果都是一样的。
针对用户定义命名空间的 using 指令的 ADL:
#include <algorithm>
namespace N
{
struct T {};
void swap(T,T) {}
}
namespace M
{
void swap(N::T,N::T) {}
}
int main()
{
using M::swap;
N::T o1,o2;
swap(o1,o2);
}
编译结果:
error C2668: 'M::swap' : ambiguous call to overloaded function
could be 'void M::swap(N::T,N::T)'
or 'void N::swap(N::T,N::T)' [found using argument-dependent lookup]
这是预期的,因为 ADL 不优先于正常查找结果,而且 ADL 不是二等公民,ADL 搜索结果与正常(非 ADL)非限定查找联合。这就是我们有歧义的原因。
针对 std 命名空间的 using 指令的 ADL:
#include <algorithm>
namespace N
{
struct T {};
void swap(T,T) {} //point 1
}
namespace M
{
void swap(N::T,N::T) {}
}
int main()
{
using std::swap;
N::T o1,o2;
swap(o1,o2);
}
这个编译好了。
结果是编译器选择 ADL 结果(它优先于 std::swap),这意味着将调用 'point 1' 处的 N::swap()。只有在没有“第 1 点”的情况下(比如我注释掉那行),编译才会使用回退 std::swap 来代替。
请注意,这种方式已在许多地方用作覆盖std::swap 的一种方式。
但我的问题是,为什么 ADL 优先于 'std namespace'(case2) 但被认为等于用户定义的命名空间函数(case1)?
C++ 标准中有一段这样说吗?
================================================ ==================================== 阅读有用的答案后编辑,可能对其他人有帮助。
所以我已经调整了我的 sn-p 1 并且现在歧义已经消失并且在进行重载解析时编译显然更喜欢非模板函数!
#include <algorithm>
namespace N
{
struct T {};
void swap(T,T) {}
}
namespace M
{
template<class T>
void swap(N::T,N::T) {}
}
int main()
{
using M::swap;
N::T o1,o2;
swap(o1,o2); //here compiler choose N::swap()
}
我还调整了我的 sn-p 2。只是为了让模棱两可看起来只是为了好玩!
#include <algorithm>
namespace N
{
struct T {};
template<class _Ty> inline
void swap(_Ty& _Left, _Ty& _Right)
{
_Ty _Tmp = _Move(_Left);
_Left = _Move(_Right);
_Right = _Move(_Tmp);
}
}
namespace M
{
void swap(N::T,N::T) {}
}
int main()
{
using std::swap;
N::T o1,o2;
swap(o1,o2);
}
gcc 和 comeau 都表示模棱两可:
"std::swap" matches the argument list, the choices that match are:
function template "void N::swap(_Ty &, _Ty &)"
function template "void std::swap(_Tp &, _Tp &)"
BTW VC10 像往常一样愚蠢,除非我删除“使用 std::swap”,否则让这个通过就好了。
还有一点要写:C++ 重载可能很棘手(C++ 标准中 30+ 页),但在附录 B 中有一个非常易读的 10 页...
感谢所有精彩的输入,现在很清楚了。
【问题讨论】:
标签: c++ namespaces using-directives argument-dependent-lookup