member function hiding free function - c++

void foo(int)
{
}
class X
{
void foo()
{
}
void bar()
{
foo(42);
// error: no matching function for call to 'X::foo(int)'
// note: candidate is:
// note: void X::foo()
// note: candidate expects 0 arguments, 1 provided
}
};
Why is C++ unable to call the free function (which is the only one with the correct signature)?

Because the two identifiers are defined in different scopes, and overload resolution only concerns about functions in the same scope. Once the compiler finds that the class has a foo, it stops climbing up to wider scopes (C++11 §3.4.1/1), so the free function foo is hidden.
You need to use a qualified name to refer to the global foo:
::foo(42);

The logical reason is Consistency.
Suppose as per the suggestion, compiler resolves foo(42) to
::foo(int).
Now after sometime, if you change X::foo() to X::foo(int) then
foo(42) will be resolved to X::foo(int). Which is not consistent.
That is the also the reason why derived class function hides base class function when there are similar names.
Such cases can be resolved in 2 ways;
(1) Give fully qualified name (e.g. ::foo(42))
(2) Use using utility; e.g.
void bar()
{
using ::foo;
foo(42);
}

A name in an inner scope hides names in outer scopes. It doesn't matter if it is a function or something else, or if you are in a class or a namespace.
Only if the name lookup finds several functions with the same name will the overload resolution kick in to try to select the one that is the best match for the call.

Really like your question. Also I could say, use this syntax:
::foo(42);
But I can say that in my opinion it's more elegant and good programming, set namespaces, so you can write something like this:
namespace MyNameSpace
{
void foo(int){}
class X
{
void foo(){}
void bar()
{
MyNameSpace::foo(42);
}
};
};
This is a good thing because Namespaces allow to group classes, objects and functions under a name.
PS: Then this help you to understand the meaning of write ::foo(42); when you haven't any namespace.

I cannot answer the why part of your question -- I do not know what was the rationale behind that in the language spec.
To call the global function in your example, use the :: syntax:
::foo(42);

The reason for this is the fact, that the compiler will look for a matching function name first, ignoring return values and parameters. When inside a class, it will try to look for a matching member there (in fact, it will look through all scopes going "upwards"; local scope(s), function scope, class scope, namespace scope, global scope, etc.).
X::foo is the first matching name. THEN (not before) it will try to pick the right overload (if there are multiple declarations) based on the parameters (which is the reason you can overload the same function with different parameters but not different return values only) and then it will check the return value (if there's any).

Related

Function overload outside class not seen

Consider following code snippet:
enum class Bar {
A
};
void foo(Bar) {}
struct Baz {
void foo() {
foo(Bar::A);
}
};
It fails to compile, the message from gcc 9.2 is:
:12:19: error: no matching function for call to 'Baz::foo(Bar)'
12 | foo(Bar::A);
|
I don't suspect it is a bug since clang 10 also fails. I have two questions regarding this situation:
Where does standard define bahaviour for such overloads?
What are the possible reasons that compiler behaviour is specified that way?
live example
The call to foo inside Baz::foo() will only look up names inside the class. If you mean to use the foo declared outside the class Baz, you need to use the scope-resolution operator, like this:
enum class Bar {
A
};
void foo(Bar) {}
struct Baz {
void foo() {
::foo(Bar::A); // looks up global 'foo'
}
};
Note that the unscoped call to foo fails because there is a Bar::foo that is found in the closest scope. If you name the function differently, then no function is found in Bar, and the compiler will look in the outer scope for the function.
enum class Bar {
A
};
void foo(Bar) {}
struct Baz {
void goo() { // not 'foo'
foo(Bar::A); // this is fine, since there is no 'Bar::foo' to find
}
};
Here's the quote from cppreference for a class definition.
e) if this class is a member of a namespace, or is nested in a class that is a member of a namespace, or is a local class in a function that is a member of a namespace, the scope of the namespace is searched until the definition of the class, enclosing class, or function. if the lookup of for a name introduced by a friend declaration: in this case only the innermost enclosing namespace is considered, otherwise lookup continues to enclosing namespaces until the global scope as usual.
Of course, this only applies to class definitions, but for member functions (which is your example), it says
For a name used inside a member function body, a default argument of a member function, exception specification of a member function, or a default member initializer, the scopes searched are the same as in [class definition], ...
So the same logic applies.
According to the rule of unqualified name lookup, from the standard, [basic.lookup.unqual]/1,
(emphasis mine)
In all the cases listed in [basic.lookup.unqual], the scopes are searched for a declaration in the order listed in each of the respective categories; name lookup ends as soon as a declaration is found for the name.
That means the name foo is found at the class scope (i.e. the Baz::foo itself), then name lookup stops; the global one won't be found and considered for the overload resolution which happens later.
About your 2nd question, functions can't be overloaded through different scopes; which might cause unnecessary confusion and complexity. Consider the following code:
struct Baz {
void foo(int i) { }
void foo() {
foo('A');
}
};
You know 'A' would be converted to int then passed to foo(int), that's fine. If functions are allowed to be overloaded through scopes, if someday a foo(char) is added in global scope by someone or library, behavior of the code would change, that's quite confusing especially when you don't know about the adding of the global one.

How can you check if one name refers to the same symbol as another?

I'd like to check if a fully-qualified name and an unqualified or partly-qualified name refer to the same symbol, even if one name isn't defined. That is, I'd like to be able to write something like this as part of a refactoring tool:
namespace A {
void f() {};
}
namespace B {
namespace A {};
bool g() {
// returns false
return is_same_symbol<A::f, ::A::f>::value;
}
}
namespace C {
bool h() {
// returns true
return is_same_symbol<A::f, ::A::f>::value;
}
}
You clarify in a comment:
I'm trying to figure out the correct SFINAE incantation for this to check if a free function of a given name exists.
You can't.
When you say a free function called foo exists, what do you mean?
It has to be one of:
The compiler has seen a declaration of foo:
... int foo(int i);
or:
The compiler has seen a definition of foo:
... int foo(int i) {
...
return ...;
}
A definition is also a declaration, so if the compiler has not
seen a declaration of foo then it hasn't seen a definition either.
Suppose you're trying to SFINAE-probe whether foo is declared.
If the compiler has not even seen a declaration of foo then any
subsequent code you write that uses foo as a name will provoke
a compile error in the vein:
error: use of undeclared identifier 'foo'
You can't write code to SFINAE-probe whether foo is declared because
you can't write C++ that uses undeclared names, period.
Suppose you're trying to SFINAE-probe whether foo is defined.
To do that, you'd first have to have declaration of foo - either
one you've written yourself or one that you've got from some header file.
But of course, given a declaration of foo, the compiler can't tell whether
or not it is defined and doesn't care, except in the special cases that the function
is declared as static or inline or in an anonymous namespace.
Otherwise, it leaves the finding or not finding of a definition to the linker.
Generally then, SFINAE-probing the existence of function definitions is likewise
a non-starter. And even if foo is declared static
or inline or in an anonymous namespace, and lacks a definition within the compilation unit, any
code that uses foo in conformity with its declaration remains well-formed
code; so even in those cases SFINAE-probing for is-it-defined remains meaningless.

Why do member names hide type-dependent name lookup? [duplicate]

void foo(int)
{
}
class X
{
void foo()
{
}
void bar()
{
foo(42);
// error: no matching function for call to 'X::foo(int)'
// note: candidate is:
// note: void X::foo()
// note: candidate expects 0 arguments, 1 provided
}
};
Why is C++ unable to call the free function (which is the only one with the correct signature)?
Because the two identifiers are defined in different scopes, and overload resolution only concerns about functions in the same scope. Once the compiler finds that the class has a foo, it stops climbing up to wider scopes (C++11 §3.4.1/1), so the free function foo is hidden.
You need to use a qualified name to refer to the global foo:
::foo(42);
The logical reason is Consistency.
Suppose as per the suggestion, compiler resolves foo(42) to
::foo(int).
Now after sometime, if you change X::foo() to X::foo(int) then
foo(42) will be resolved to X::foo(int). Which is not consistent.
That is the also the reason why derived class function hides base class function when there are similar names.
Such cases can be resolved in 2 ways;
(1) Give fully qualified name (e.g. ::foo(42))
(2) Use using utility; e.g.
void bar()
{
using ::foo;
foo(42);
}
A name in an inner scope hides names in outer scopes. It doesn't matter if it is a function or something else, or if you are in a class or a namespace.
Only if the name lookup finds several functions with the same name will the overload resolution kick in to try to select the one that is the best match for the call.
Really like your question. Also I could say, use this syntax:
::foo(42);
But I can say that in my opinion it's more elegant and good programming, set namespaces, so you can write something like this:
namespace MyNameSpace
{
void foo(int){}
class X
{
void foo(){}
void bar()
{
MyNameSpace::foo(42);
}
};
};
This is a good thing because Namespaces allow to group classes, objects and functions under a name.
PS: Then this help you to understand the meaning of write ::foo(42); when you haven't any namespace.
I cannot answer the why part of your question -- I do not know what was the rationale behind that in the language spec.
To call the global function in your example, use the :: syntax:
::foo(42);
The reason for this is the fact, that the compiler will look for a matching function name first, ignoring return values and parameters. When inside a class, it will try to look for a matching member there (in fact, it will look through all scopes going "upwards"; local scope(s), function scope, class scope, namespace scope, global scope, etc.).
X::foo is the first matching name. THEN (not before) it will try to pick the right overload (if there are multiple declarations) based on the parameters (which is the reason you can overload the same function with different parameters but not different return values only) and then it will check the return value (if there's any).

Why class member functions shadow free functions with same name?

It recently came to my attention that member functions completely shadow free functions with the same name when inside the class. And by completely I mean that every free function with the same name is not considered for overload resolution at all. I can understand why it's done with something like this:
void f();
struct S
{
void f();
void g()
{
f(); // calls S::f instead of ::f
}
};
where the functions have identical signatures, its only natural as variable scoping works the same way. But why prohibit unambigious calls where free function has different signature like this:
void f();
struct S
{
void f(int x);
void g()
{
f(); // fails to compile attempting to call S::f, which has wrong signature
}
};
I am not asking how to call a shadowed free function from inside the class. What i want to know is the rationale behind this design.
For unqualified name lookup, only one scope at a time is considered, and if the search in that scope doesn't yield any results, the next higher scope is searched. In your case, only S's scope is searched.
But why prohibit unambigious calls where free function has different signature like this:
The problem is that name lookup doesn't concern itself with anything but the name, the identifier. It is completely oblivious to the fact that you want to call a function, it just sees an identifier. The same name lookup happens if you just use auto x = f;, and if you think of it that way, there are very good reasons you only want a very limited scope to search. Anything else would just surprise the user.
There is a special, very surprising, rule (but it does not apply to your example) stating that once a class member name is found by name lookup, no namespace scopes are searched:
#include <string>
struct C {
std::string s;
explicit C (std::string);
void swap (C& rhs) {
swap (s, rhs.s); // error: swap is C::swap
}
};
void swap (C& lhs, C& rhs) {
swap (lhs.s, rhs.s); // std::swap(string,string)
}
IMO, this is craziness.
But why prohibit unambigious calls where free function has different signature like this:
Name lookup happens before overloading resolution:
If lookup is ambiguous, overloading resolution is not done.
If no viable function is found by name lookup, no other round of lookup is tried.
The rules are sufficiently complex without "feedback" between overloading and name lookup. I would suggest simplification (like removing the member hides namespace scope name rule, and removing ambiguous name lookup) rather than complexification.
I cannot provide an authoritative answer (Maybe some remember a quote from Design and Evolution of C++ or actually has been on the committee at that time), but my first guess would be to exactly fail in cases as you show. It is easy to forget how many things are in scope at a certain time. Additionally overload resolution can be quite complex and there can be default arguments and conversion. So I'd rather have the most limited scope in that case to be always sure what exactly is being called.

Nested functions are not allowed but why nested function prototypes are allowed? [C++]

I was reading the linked question which leads me to ask this question.
Consider the following code
int main()
{
string SomeString();
}
All says, compiler takes this as a function prototype and not as a string object. Now consider the following code.
int main()
{
string Some()
{
return "";
}
}
Compiler said this is invalid as I guess nested function definition is not allowed. If it is not allowed, why nested function prototypes are allowed? It is not giving any advantage rather than making confusion (or am I missing some valid points here?).
I figured out the following is valid.
int main()
{
string SomeFun();
SomeFun();
return 0;
}
string SomeFun()
{
std::cout << "WOW this is unexpected" << std::endl;
}
This is also confusing. I was expecting the function SomeFun() will have a scope only in main. But I was wrong. Why compiler is allowing to compile code like the above? Is there any real time situations where code like the above makes sense?
Any thoughts?
Your prototype is just 'Forward Declaration'. Please check out the Wikipedia article.
Basically, it tells the compiler "don't be alarmed if the label 'SomeFun' is used in this way". But your linker is what's responsible for finding the correct function body.
You can actually declare a bogus prototype, e.g. 'char SomeFun()' and use it all over your main. You will only get an error when your linker tries to find the body of your bogus function. But your compiler will be cool with it.
There are lots of benefits. You have to remember the function body is not always in the same source code file. It can be in a linked library.Also, that linked library may be have a specific 'link signature'.Use conditional defines you may even select the correct link signature at build time using your scoped prototypes.Although most people would use function pointers for that instead.
Hope this helps.
Just as a side note, C++03 does have a roundabout way of defining local functions. It requires abusing the local-class feature:
int main()
{
struct Local
{
static string Some()
{
return "";
}
};
std::cout << Local::Some() << std::endl;
}
This is a convention from C -- like many -- which C++ has adopted.
The ability to declare a function inside another function in C is a decision that most programmers probably consider regrettable and unnecessary. Particularly with modern OOP design where function definitions are comparatively smaller than they are in C.
If you would like to have functions that only exist in the scope of another function, two options are boost::lambda and C++1x lambda.
As to why your declaration of
void f() {
void g(); g();
}
is better than this one
void g();
void f() {
g();
}
It's generally good if you keep declarations as local as possible, so that as few name clashes as possible result. I say it's arguable whether declaring a function locally (this way) is really fortunate, as i think it's still better to ordinary include its header and then go the "usual" way, which is also less confusing to people not knowing about that. Sometimes, it's also useful to work around a shadowed function
void f() {
int g;
// oops, ::g is shadowed. But we can work around that
{
void g(); g();
}
}
Of course, in C++ we could call function g using its_namespace::g() - but in the old days of C, that wouldn't have been possible, and that thing allowed the programmer to still access the function. Also note that while syntactically it is not the same, semantically the following does also declare a function within a local scope, that actually targets a different scope.
int main() {
using std::exit;
exit();
}
As a side note, there are more situations like that where the target scope of a declaration is not the scope where that declaration appears in. In general, the entity you declare becomes a member of the scope in which the declaration appears. But that's not always the case. Consider for example friend declarations, where that thing happens
struct X { friend void f() { std::cout << "WoW"; } };
int main() { void f(); f(); } // works!
Even though the function declaration (and definition!) of f happened within the scope of X, the entity (the function itself) became a member of the enclosing namespace.
Function prototypes are hints for the compiler. They indicate that the functions are implemented somewhere else, if not already discovered. Nothing more.
When you declare a prototype as you are doing you are basically telling the compiler to wait for the linker to resolve it. Depending where you write the prototype the scoping rules apply. There is nothing technically wrong writing the prototype inside your main() function (although IMHO a bit messier), it just means that the function is only locally known inside the main(). If you would have declared the prototype at the top of your source file (or more commonly in a header file), the prototype/function would be known in the whole source.
string foo()
{
string ret = someString(); // Error
return ret;
}
int main(int argc,char**argv)
{
string someString();
string s = somestring(); // OK
...
}