2017-08-16 22 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