Gob*_*0st 6 c++ namespaces using-directives argument-dependent-lookup
我有两个用于ADL的片段用于演示目的.这两个片段都是由VC10,gcc和comeau C++编译器编译的,结果对于这三个片段都是相同的.
<1> 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);
}
Run Code Online (Sandbox Code Playgroud)
编译结果:
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]
Run Code Online (Sandbox Code Playgroud)
这是预期的,因为ADL不优先于正常查找结果加上ADL不是二等公民,ADL搜索结果与正常(非ADL)无法定义查找联合.这就是为什么我们有歧义.
<2> ADL反对使用std命名空间的指令:
#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);
}
Run Code Online (Sandbox Code Playgroud)
这个编译好了.
结果是编译器选择ADL结果(它采用std :: swap的先例),这意味着N::swap()将调用'point 1'.只有在缺少"第1点"时(比如我注释掉那一行),编译才会使用后退std::swap.
注意这种方式已被用于许多地方作为覆盖的方式std::swap.但我的问题是,为什么ADL优先于'std namespace'(case2)但被认为等于用户定义的命名空间函数(case1)?
C++标准中是否有段落这样说?
================================================== ===============================阅读有用的答案后编辑,可能对其他人有所帮助.
所以我已经调整了我的代码片段1,现在模糊性消失了,并且在进行重载分辨率时,编译显然更喜欢Nontemplate函数!
#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()
}
Run Code Online (Sandbox Code Playgroud)
我也调整了我的片段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);
}
Run Code Online (Sandbox Code Playgroud)
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 &)"
Run Code Online (Sandbox Code Playgroud)
BTW VC10像往常一样愚蠢,让这个通过ok,除非我删除'using std :: swap'.
写一点:C++重载可能很棘手(C++标准中有30多页),但在appendlix B中有一个非常易读的10页...
感谢所有不错的输入,现在很清楚.
Xeo*_*Xeo 11
函数调用分几个阶段进行†:
你将第1部分与第3部分混淆.名称查找实际上将两个swap函数放在重载集({N::swap, std::swap})中,但第3部分将决定,最后调用哪一个.
现在,既然std::swap是一个模板,标准说在进行重载解析时,非模板函数比模板函数更专业,你的<2>调用N::swap:
§13.3.3 [over.match.best] p1
鉴于这些定义,如果[...] ,可行功能
F1被定义为比另一个可行功能更好的功能F2.
F1是一个非模板函数,F2是一个功能模板专业化[...]
†我推荐这个优秀系列的前三个视频.
Dav*_*eas 10
您的测试不会检查ADL是否优先于通常查找,而是检查重载决策如何确定最佳匹配.第二个测试用例的工作原理是std::swap模板,当对完美匹配(由ADL找到)和模板执行重载决策时,非模板化函数优先.
| 归档时间: |
|
| 查看次数: |
1169 次 |
| 最近记录: |