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;
}

Why memcpy is ambigious call here?

Please take a look at example with variable "i" in ANSI ISO IEC 14882, C++2003, 3.4.1, (6) (page 30). It "proves" that there is no ambigioty in such construction.

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
}

Is unqualified lookup rules was broken in GCC or I did not understand something?

songyuanyao
  • 169,198
  • 16
  • 310
  • 405
Konstantin Burlachenko
  • 5,233
  • 2
  • 41
  • 40

1 Answers1

6

The name to be looked up is function name; the special argument-dependent lookup rule takes effect here. (Note that ADL is a part of the unqualified name lookup for function names.)

These function names are looked up in the namespaces of their arguments in addition to the scopes and namespaces considered by the usual unqualified name lookup.

At first you include string.h, which introduces the name memcpy in global namespace.

And AA is declared in global namespace; then when you call memcpy(&a, &a, sizeof(a));, the namespace where AA is declared (i.e. the global namespace) will be considerted too, and the memcpy declared in namespace my will be found by usual unqualified name lookup, so the calling is ambiguous.

On the other hand, BB doesn't have such issue because it's not declared in global namespace (and then ADL won't take effect for it).

songyuanyao
  • 169,198
  • 16
  • 310
  • 405
  • Thanks. Looks that you're absolutely right. When I read book of B.Stroustroup, The C++ Programming Language: Special Edition (3rd Edition) (Russian translate), p.221, 8.2.6 Search names - it have been said "If the function is not found in the context of its use, an attempt is made to search the namespace of the arguments". Looks that Standrtized comittete changed rules a bit. – Konstantin Burlachenko Aug 16 '17 at 13:10
  • 1
    @bruziuz It might be a description issue, I often encountered such problem when reading translated book; precisely it should be "all the names found by ADL and usual unqualified name lookup will be added to the name set, then overload resolution will determine which one should be called". – songyuanyao Aug 16 '17 at 13:16