I have the following simplified code
namespace Namespace
{
int foo() { return 1; }
class Class
{
public:
int foo() const { return 2; }
class Nested {
public:
Nested()
{
cout << foo() << endl;
}
};
};
}
And I got this error:
error: cannot call member function ‘int Namespace::Class::foo() const’ without object:
cout << foo() << endl;
^^^^^
It seems that compiler selects non static int Namespace::Class::foo() const
instead of global function int Namespace::foo()
.
But how can it be expected that non-static function from other class can be called without object? Nested object
has no access to surrounding Class object
- this is not Java after all.
I read carefully through overload resolution from cppreference I cannot find the rationale for this behavior. I rather doubt that this is gcc error.
- Can you point the language rules responsible for this behavior?
- And how do you deal with such problems?
[UPDATE]
Just an answer for 2nd question. Workaround is simple, there is a need to tell compiler that such global function exists:
Nested()
{
using Namespace::foo; //< workaround: inform compiler such function exists
cout << foo() << endl;
}
BTW, is that workaround correct? Are there any better solutions?
Before the overload resolution procedure selects the best viable function, an initial set of candidates is generated during the name lookup phase. In other words, the expected behavior should be searched for in the Name lookup section, not in the Overload resolution one.
The name lookup procedure for an unqualified name is described in the C++ standard:
§3.4.1 [basic.lookup.unqual]/p8:
and only if still not found:
Since the name lookup ends as soon as the name is found (§3.4.1 [basic.lookup.unqual]/p1):
in your case no other scopes are searched as soon as
int foo() const { return 2; }
is encountered.§7.3.3 [namespace.udecl]/p1:
§3.3.1 [basic.scope.declarative]/p1:
Introducing a name with a using-declaration impacts the unqualified name lookup in a way such that it finds that function in its first step, namely that name becomes declared:
One can use a qualified name when referring to a function from some namespace scope, explicitly indicating what symbol is being referred to: