#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?
An unqualified name is simply the class, interface, enum or field without package information.
A function call expression such as func(a,b,c) , in which the function is named without the :: scope operator, is called unqualified.
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>
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With