below code cannot be compiled: ----------- #define TYPE N::C #define ASSIGN do {} while(0) //#define ASSIGN do { x->i = 0;} while(0) //#define TYPE N::B namespace N { class B; class C; } void func(TYPE * x); namespace N { class B { int i; }; class C { int i; friend void func(TYPE * x); }; } void func(TYPE * x) { ASSIGN; } int main() { TYPE x; func(&x); return 0; } ----------- g++ report: ------------ /test-cpp.cpp: In function 'int main()': ./test-cpp.cpp:22: error: call of overloaded 'func(N::C*)' is ambiguous ./test-cpp.cpp:18: note: candidates are: void func(N::C*) ./test-cpp.cpp:15: note: void N::func(N::C*) ------------ change #define TYPE N::C to #define TYPE N::B then the code can be compiled. According to [namespace.memdef] and [basic.scope.pdecl]: --------------- friend declarations refer to functions or classes that are members of the nearest enclosing namespace, but they do not introduce new names into that namespace (7.3.1.2). --------------- According to standard, ::func(N::C * x) shouldn't become friend of N::C, but there should no ambiguous, because 'friend void func(TYPE * x);' look for N::func(N::C *), and it doesn't exist at all. According to [namespace.memdef], the names introduced by 'friend' is invisible until its real declaration. It seems that, g++ wrongly introduces a name: N::func(N::C*) into namespace N, and when calling func(N::C*), it follows koenig lookup and finds N::func(N::C*). In the situation of 'friend void N::func(N::B*)', g++ works correctly.
following is my g++ -v: Using built-in specs. Target: i686-pc-linux-gnu Configured with: /var/tmp/portage/sys-devel/gcc-4.3.4/work/gcc-4.3.4/configure --prefix=/usr --bindir=/usr/i686-pc-linux-gnu/gcc-bin/4.3.4 --includedir=/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include --datadir=/usr/share/gcc-data/i686-pc-linux-gnu/4.3.4 --mandir=/usr/share/gcc-data/i686-pc-linux-gnu/4.3.4/man --infodir=/usr/share/gcc-data/i686-pc-linux-gnu/4.3.4/info --with-gxx-include-dir=/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4 --host=i686-pc-linux-gnu --build=i686-pc-linux-gnu --disable-altivec --disable-fixed-point --enable-nls --without-included-gettext --with-system-zlib --disable-checking --disable-werror --enable-secureplt --disable-multilib --enable-libmudflap --disable-libssp --enable-libgomp --disable-libgcj --with-arch=i686 --enable-languages=c,c++,treelang,fortran --enable-shared --enable-threads=posix --enable-__cxa_atexit --enable-clocale=gnu --with-bugurl=http://bugs.gentoo.org/ --with-pkgversion='Gentoo 4.3.4 p1.0, pie-10.1.5' Thread model: posix gcc version 4.3.4 (Gentoo 4.3.4 p1.0, pie-10.1.5)
This is correct argument dependent lookup is supposed to find N::func for N::C. You just cannot call N::func directly.
Then why #define TYPE N::B works? why argument dependent lookup doesn't take effect? Both B and func are in namespace N.
(In reply to comment #3) > Then why > > #define TYPE N::B > > works? > > why argument dependent lookup doesn't take effect? Both B and func are in > namespace N. Because N::func is only a friend of N::C so it is only found for N::C.
I find a clause in the standard: [basic.lookup.argdep]: Any namespace-scope friend functions or friend function templates declared in associated classes are visible within their respective namespaces even if they are not visible during an ordinary lookup. g++ is right.