在C++中进行不合格的查找

bru*_*iuz 5 c++ g++ language-lawyer name-lookup

#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;
}
Run Code Online (Sandbox Code Playgroud)

为什么memcpy在这里打电话?

请查看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
}
Run Code Online (Sandbox Code Playgroud)

GCC中是否打破了不合格的查找规则或者我不理解某些内容?

son*_*yao 6

要查找的名称是函数名称; 特殊参数依赖查找规则在此处生效.(请注意,ADL是函数名称的非限定名称查找的一部分.)

除了通常的非限定名称查找所考虑的范围和名称空间之外,还会在其参数的名称空间中查找这些函数名称.

首先是include string.h,它memcpy在全局命名空间中引入了名称.

AA在全局命名空间中声明; 然后当你调用时memcpy(&a, &a, sizeof(a));,AA也会考虑声明的命名空间(即全局命名空间),并且通常通过非限定名称查找memcpy命名空间中的声明,因此调用是不明确的.my

另一方面,BB没有这样的问题,因为它没有在全局命名空间中声明(然后ADL不会对它生效).