2017-08-16 53 views
5
#include <stdio.h> 
#include <cstddef> 
#include <cstring> 

namespace /*namespace name generated by compiler*/ 
{ 
    struct BB{}; 
} 

struct AA{}; 

namespace my 
{ 
    inline void * memcpy(void*, const void*, std::size_t) 
    { 
     puts("CUSTOM IMPLEMENTATION"); 
     return 0; 
    } 
} 

namespace my 
{ 
    void func() 
    { 
     AA a; 
     memcpy(&a, &a, sizeof(a)); // ambigious call for g++4.7 - g++6.2 

     BB b; 
     memcpy(&b, &b, sizeof(b)); // unambigious call 

    } 
} 

int main(int, char **) 
{ 
    my::func(); 
    return 0; 
} 

爲什麼的memcpy是ambigious通話嗎?不合格查找

請參考ANSI ISO IEC 14882,C++ 2003,3.4.1,(6)(第30頁)中變量「i」的示例。它「證明」在這樣的建設中沒有任何不安。

namespace A { 
    namespace N { 
    void f(); 
    } 
} 
void A::N::f() { 
    i = 5; 
// The following scopes are searched for a declaration of i: 
// 1) outermost block scope of A::N::f, before the use of i 
// 2) scope of namespace N 
// 3) scope of namespace A 
// 4) global scope, before the definition of A::N::f 
} 

是不合格的查找規則在GCC中被破壞還是我不明白?

+0

您能否包含C++ 2003的示例,第30頁。 3.4.1,(6)? – user463035818

+0

更好地發佈這裏的例子。 – CinCout

+2

如果您希望我們引用語言標準的某個特定部分,那麼如果您引用*標準的相關部分將會更有幫助。 –

回答

6

要查找的名稱是函數名稱;特殊的argument-dependent lookup規則在此處生效。 (請注意,ADL是unqualified name lookup對函數名的一部分。)

這些函數名,除了用通常的不合格的名稱查找考慮的範圍和名稱空間擡頭在他們的論據的命名空間。

首先包含string.h,它在全局命名空間中引入名稱memcpy

AA在全局命名空間中聲明;那麼當你調用memcpy(&a, &a, sizeof(a));時,聲明AA的命名空間(即全局命名空間)也將被考慮,並且在命名空間my中聲明的memcpy將通過常見的unqualified name lookup找到,所以調用是不明確的。

另一方面,BB沒有這樣的問題,因爲它沒有在全局名稱空間中聲明(然後ADL將不會生效)。

+0

謝謝。看起來你是對的。當我讀到B.Stroustroup的書時,C++編程語言:特別版(第3版)(俄文翻譯),p.221,8.2.6搜索名稱 - 有人說過「如果函數沒有在它的使用,嘗試搜索參數的命名空間「。看起來,Standrtized comittete改變了一些規則。 – bruziuz

+1

@bruziuz這可能是一個描述問題,我在閱讀翻譯的書時經常遇到這樣的問題;確切地說,它應該是「ADL發現的所有名稱,並且通常的非限定名稱查找將被添加到名稱集合中,然後重載決議將決定應該調用哪一個名稱」。 – songyuanyao