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?
Namespace is a feature added in C++ and is not present in C. A namespace is a declarative region that provides a scope to the identifiers (names of functions, variables or other user-defined data types) inside it. Multiple namespace blocks with the same name are allowed.
Filename collisions are easy to prevent by being systematic: organize your headers so that they mimic your namespaces, e.g. boost::numeric::ublas::vector<> comes from #include <boost/numeric/ublas/vector.
Similarly, C++ requires that all identifiers be non-ambiguous. If two identical identifiers are introduced into the same program in a way that the compiler or linker can't tell them apart, the compiler or linker will produce an error. This error is generally referred to as a naming collision (or naming conflict).
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.
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