views:

284

answers:

4

I cannot understand why this piece of code does not compile:

namespace A {
        class F {};             // line 2
        class H : public F {};
}

namespace B {
        void F(A::H x);         // line 7
        void G(A::H x) {
                F(x);           // line 9
        }
}

I am using gcc 4.3.3, and the error is:

s3.cpp: In function ‘void B::G(A::H)’:
s3.cpp:2: error: ‘class A::F’ is not a function,
s3.cpp:7: error:   conflict with ‘void B::F(A::H)’
s3.cpp:9: error:   in call to ‘F’

I think that because in line 9 there is no namespace prefix, F(x) should definitively mean only B::F(x). The compiler tries to cast x into its own superclass. In my understanding it should not. Why does it do that?

+10  A: 

That's because compiler will search function in the same namespace its arguments from. Compiler found there A::F identifier but it is not a function. In result you'll get the error.

It is standard behaviour as far as I can remember.

3.4.2 Argument-dependent name lookup When an unqualified name is used as the postfix-expression in a function call (5.2.2), other namespaces not considered during the usual unqualified lookup (3.4.1) may be searched, and namespace-scope friend function declarations (11.4) not otherwise visible may be found. These modifications to the search depend on the types of the arguments (and for template template arguments, the namespace of the template argument).

For each argument type T in the function call, there is a set of zero or more associated namespaces and a set of zero or more associated classes to be considered. The sets of namespaces and classes is determined entirely by the types of the function arguments (and the namespace of any template template argument). Typedef names and using-declarations used to specify the types do not contribute to this set. The sets of namespaces and classes are determined in the following way...

This rule allows you to write the following code:

std::vector<int> x;
// adding some data to x
//...

// now sort it
sort( x.begin(), x.end() ); // no need to write std::sort

And finally: Because of Core Issue 218 some compilers would compile the code in question without any errors.

Kirill V. Lyadvinsky
So-called Koenig lookup, in fact, described in section 3.4.2 of the C++ Standard.
anon
Then if VS compiles this, it is a bug?
liori
Could you find a reference to that statement? I've never heard of any rule like that...
xtofl
@Neil, you're right. Added a quote just in case.
Kirill V. Lyadvinsky
@liori, VS compiles this because of Core Issue 218.
Kirill V. Lyadvinsky
+4  A: 

Have you tried using other compilers yet? There is a gcc bug report here which is suspended (whatever that means).

EDIT: After some research, I found this more official bug.

schnaader
This is a minimal example of my own code which does compile on my friend's VS2005. I haven't tested this exact piece though. And... DeusAduro seems to have no problem compiling it on VS2005.
liori
The bug report looks quite like this, though it involves templates, which have a yet different (two-phase) lookup scheme.
xtofl
Note: others report VS2005 to compile this code as expected. I tried Comeau's Test Drive -> success. Only gcc seems to suffer from this, it seems.
xtofl
if jia3ep's answer is correct, and I believe it is, then gcc isn't "suffering", but as usual, VS is non-conforming.
rmeador
@xtofl: At least the bug I mentioned first is available here: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=25980 and has been marked a duplicate of this bug.
schnaader
@rmeador, seems to be VS is completely conforming in the last version.
Kirill V. Lyadvinsky
+1  A: 

Very strange, I copied and pasted directly to VS 2005 and I get an error, which I expected:

Error 1 error LNK2001: unresolved external symbol "void __cdecl B::F(class A::H)"

Because we haven't actually defined F(x) in namespace B... not sure why Gcc is giving this error.

DeusAduro
A: 

I just tried compiling it on Visual Studio 2005 and it worked fine. I wonder if it's a broken implementation of Argument Dependent Lookup where the namespace from the arguments was accidentally brought in?

Matt Price