Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unqualified lookup in C++

#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?

like image 474
Konstantin Burlachenko Avatar asked Aug 16 '17 12:08

Konstantin Burlachenko


People also ask

What does unqualified name mean?

An unqualified name is simply the class, interface, enum or field without package information.

What is unqualified call C++?

A function call expression such as func(a,b,c) , in which the function is named without the :: scope operator, is called unqualified.

What is name lookup?

Name lookup is the procedure by which a name, when encountered in a program, is associated with the declaration that introduced it. For example, to compile std::cout << std::endl;, the compiler performs: unqualified name lookup for the name std , which finds the declaration of namespace std in the header <iostream>


1 Answers

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).

like image 55
songyuanyao Avatar answered Sep 19 '22 19:09

songyuanyao