我有兩個用於演示目的的ADL代碼片段。這兩個片段已經由VC10,gcc & comeau C++編譯器編譯,結果對於所有三個都是相同的。爲什麼ADL優先於'std命名空間'中的函數,但等於用戶定義的命名空間中的函數?
< 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);
}
編譯結果:
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)未滿足的查找結合。這就是爲什麼我們有歧義。
< 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);
}
這一個編譯確定。
結果是編譯器選擇ADL結果(它採用std :: swap的先例),意思是N::swap()
在'點1'將被調用。只有在缺乏'第一點'的情況下(比如說我註釋掉那一行),編譯纔會使用倒退std::swap
來代替。
注意這種方式已被用在許多地方作爲覆蓋std::swap
的方式。 但我的問題是,爲什麼ADL優先於'std命名空間'(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()
}
我也調整了我的片段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和科莫都表示,不確定性預期:
"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愚蠢像往常一樣讓這一個傳球ok了,除非我刪除了 '使用std ::交換'。
只是有點越寫:C++超載可能會非常棘手(30+頁C++標準),但在appendlix B的存在是一個非常可讀的10頁還有......
感謝所有的美好投入,現在很明顯。
值得注意的一點是,ADL屬於*名稱查找*,並且名稱查找沒有「優先級」的概念。 –
@KerrekSB:我認爲David在名稱查找階段討論的是重載分辨率,而這一切都是關於選擇最佳匹配的。 – Gob00st