Inferring namespace of freestanding function - c++

Question on namespace qualification: Why isn't the namespace of the function inferred below?
namespace X {
void func(int) {}
struct Z{
void func(){
//func(int{}); does not compile
X::func(int{}); // this works
}
};
}
int main() {
X::Z z;
z.func();
}

This specific part of C++ can be generally called "unqualified name lookup". This term describes taking a single identifier in a C++ program and then determining which actual type, or object, or function, or class, it is referencing.
For example, there can be many things called rosebud in a C++ program, so
rosebud();
This can reference a class method of this name, and this calls it. Or this could be an object with an overloaded () operator, which invokes it. There could also be something called rosebud() in a different namespace. Unqualified name lookup specifies which one of these this particular rosebud references.
struct Z{
void func(){
Here we're in a method of class Z. Unqualified name lookup first looks for identifiers that are members of this class. Only if it's not found then does unqualified name lookup looks in the global namespace, to see if something is there.
func(int{}); // does not compile
Well, there happens to be a method with the name func in this class, so this func's unqualified name lookup resolves to this method. This fails, because that func method takes no parameters.
Unqualified name lookup considers where exactly the unqualified identifier occurs. When it occurs in a class, unqualified name lookup searches the class's members, first.
Even though there's also a func function in the global scope, unqualified lookup finds the class method, and that's it (quoting from the cited link):
[unqualified] name lookup examines the scopes as described below,
until it finds at least one declaration of any kind, at which time the
lookup stops and no further scopes are examined.
End of the road. The fact that there's also a func in the global namespace is immaterial. For unqualified name lookup, once "something" is found, it better work, or else.
These are just one of the rules of unqualified name lookup.
X::func(int{}); // this works
Well, yes. This explicitly references func in the X namespace. This symbol is (partially) qualified with an explicit namespace reference.

Related

In c++ Why and how classname::member syntax can be used for an instance member?

class Human {
public:
Human(string name);
string getName() {
return Human::name;
}
void setName(string name) {
Human::name = name ;
}
private:
string name;
};
Human::name in getName and setName funcs. work perfectly although name is not a static variable.
Why is this happening ?
As far as I know "::" is used to acces functions or static members of a class.
I thought correct usage in getName would be return this -> name or return name.
And even, when generated auto setter function in Clion, setter function uses Human::name not this -> name
I'm coming from java background and in java classname.X (which resembles classname::X in c++) was only used for static members or functions of a class. That is why I am confused
First things first, you're missing a return statement inside setName, so the program will have undefined behavior.
Now, Human::name is a qualified name that refers to(or names) the non-static data member name. For qualified names like Human::name, qualified lookup happens which will find the data member name.
On the other hand, just name(without any qualification) is an unqualified name and so for it, unqualified lookup will happen which will also find the data member named name. And so you could have just used name(instead of Human::name) as it will also refer to the same non-static data member.
Basically the main difference between name and Human::name are that:
name is a unqualified name while Human::name is a qualified name.
For name unqualified lookup will happen while for Human::name qualified lookup will happen.
The similarity between the two is that:
Both at the end of the day refer to the same non-static data member.
According to the C++ 17 Standard (6.4.3 Qualified name lookup)
1 The name of a class or namespace member or enumerator can be
referred to after the :: scope resolution operator (8.1) applied to a
nested-name-specifier that denotes its class, namespace, or
enumeration. If a :: scope resolution operator in a
nested-name-specifier is not preceded by a decltype-specifier, lookup
of the name preceding that :: considers only namespaces, types, and
templates whose specializations are types. If the name found does not
designate a namespace or a class, enumeration, or dependent type, the
program is ill-formed.

Why is the ADL not working when `using directive` is used?

Here is a similar question, but in this question it works, however, it fails in the following circumstance, why?
namespace A
{
int k;
}
namespace B
{
class test{};
void k(const test&){/*do something*/}
}
int main()
{
using namespace A;
k(B::test());//compile error
}
Error message is: "'A::k' cannot be used as a function" (gcc 6.3.0)
That is to say, the compiler does not try to do ADL and never find the void k(const test&) in namespace B
However, I think the ADL should work in such situation because the code above does not belong to the following circumstance:
quoted from cppref
First, the argument-dependent lookup is not considered if the lookup set produced by usual unqualified lookup contains any of the following:
1) a declaration of a class member
2) a declaration of a function at block scope (that's not a using-declaration)
3) any declaration that is not a function or a function template (e.g. a function object or another variable whose name conflicts with the name of the function that's being looked up)
To be more precise, here the using namespace A does not introduce any declaration:
quoted from cppref
Using-directive does not add any names to the declarative region in which it appears (unlike the using-declaration), and thus does not prevent identical names from being declared.
The name lookup for a function call has two parts:
normal unqualified lookup
ADL
According to N4659 [basic.lookup.argdep]/3, the normal unqualified lookup happens first; and then ADL stage does not go ahead if the normal unqualified lookup found:
a declaration of a class member, or
a block-scope function declaration that is not a using-declaration, or
a declaration that is neither a function nor a function template.
In your code the normal unqualified lookup does find A::k as discussed in your previous question. So ADL does not happen for this code.
A using-directive specifies that the names in the nominated namespace can be used in the scope in which the using-directive appears after the using-directive. During unqualified name lookup (6.4.1), the names appear as if they were declared in the nearest enclosing namespace which contains both the using-directive and the nominated namespace.
So, unqualified name lookup will find A::k, that is the reason for the error.

Function names in global namepsace scope cannot be found

According to unqualified lookup in cppreference.com:
For a name used in the definition of a function, either in its body or as part of default argument, where the function is a member of user-declared or global namespace, the block in which the name is used is searched before the use of the name, then the enclosing block is searched before the start of that block, etc, until reaching the block that is the function body. Then the namespace in which the function is declared is searched until the definition (not necessarily the declaration) of the function that uses the name, then the enclosing namespaces, etc.
So I thought function names defined in global namespace scope shall be found simply through unquailifed lookup. However, the following piece of code fails to compile:
#include <iterator>
#include <iostream>
namespace AA{
class AAA{};
};
using namespace AA;
int begin(AAA ){
return 3;
}
int main(){
using std::begin; // to add std::begin in the name candidate set
auto x = AAA();
return begin(x); // compile error, ::begin cannot be found
}
Both GCC(6.1.1) and Clang(3.8.0) reports the same error.
And, either I remove the using std::begin statement or move class AAA to namespace AA, the above program compiles successfully. So I think once my begin is found through name lookup, it will be chosen through overload resolution. Therefore the question is: why my begin function declared and defined in global scope is simply not found in the code case above?
Note that unqualified name lookup will stop if the name is found (at some scope), then the further scopes won't be searched. For your sample code, the name begin will be found at the function scope of main(), (which refers to std::begin), then name lookup stops, so the name in global scope won't be examined.
..., name lookup examines the scopes as described below, until it finds at least one declaration of any kind, at which time the lookup stops and no further scopes are examined.
From the quotation you posted (emphasis added by me):
etc, until reaching the block that is the function body. (the name lookup will stop here, i.e. in the block of main() function body)
Then the namespace ... (The further namespace won't be searched.)

Overload Resolution: How is this not ambiguous?

Suppose we have this code, copied from a separate question:
namespace x
{
void f()
{
}
class C
{
void f()
{
using x::f;
f(); // <==
}
};
}
The name f on the indicated line unambiguously refers to x::f (at least according to both gcc and clang). Why is x::f preferred over x::C::f in this case? Shouldn't it be ambiguous as both names are visible?
Because the using declaration brings x::f into the scope of f, which is narrower than that of C. Unqualified lookup considers the local block scope, finds a match, and stops before considering the wider class scope. There is no argument-dependent lookup since there are no function arguments, so no further scopes are considered.
#MikeSeymour's answer is spot on; here are the relevant standard quotes (C++11, emphasis mine):
13.3.1.1.1/3:
In unqualified function calls, the name is not qualified by an -> or . operator and has the more general form
of a primary-expression. The name is looked up in the context of the function call following the normal rules
for name lookup in function calls (3.4). The function declarations found by that lookup constitute the set of
candidate functions. Because of the rules for name lookup, the set of candidate functions consists (1) entirely
of non-member functions or (2) entirely of member functions of some class T. ...
3.4.1/1:
In all the cases listed in 3.4.1, 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. If no declaration is
found, the program is ill-formed.
3.4.1/8
A name used in the definition of a member function (9.3) of class X following the function's declarator-id
... shall be declared in one of
the following ways:
before its use in the block in which it is used or in an enclosing block (6.3), or
shall be a member of class X or be a member of a base class of X (10.2), or
...
From 3.4.1/8, we see that a declaration for the name f (such as the declaration using x::f;) in the block in which it's used is listed earlier than f as the member of class C. As per 3.4.1/1, the earlier one is chosen, so the entire lookup resolves to x::f introduced by the using declaration.
I think that these quotes from the C++ Standard will be relevant:
From the C++ Standard (7.3.3 The using declaration)
13 Since a using-declaration is a declaration, the restrictions on
declarations of the same name in the same declarative region (3.3)
also apply to using-declarations.
And (3.3.7 Class scope)
4) A name declared within a member function hides a declaration of the
same name whose scope extends to or past the end of the member
function’s class.

Why calling a non-member function with the same name as a member function generates an error

I have next code:
void f(int){}
struct A
{
void f()
{
f(1);
}
};
This code is not well-formed with the error message (GCC): error: no matching function for call to ‘A::f(int)’ or (clang) Too many arguments to function call, expected 0, have 1; did you mean '::f'?
Why do I need to use :: to call the non-member function with the same name as the member function, but with different signature? What is the motivation for this requirement?
I think the compiler should be able to figure it out I want to call the non-member function as the signature is different (clang even puts that in the error message!).
Please don't mark this as duplicate - it is a different question from this Calling in C++ a non member function inside a class with a method with the same
Why do I need to use :: to call the non-member function with the same name as the member function, but with different signature
Because those are the rules. Names in a nested scope hide entities with the same name in a wider scope.
What is the motivation for this requirement?
Consider the case where a member function calls another member with a signature that doesn't quite match:
struct A {
void f(double);
void g() {f(42);} // requires int->double conversion
};
Now suppose someone adds an unrelated function in the surrounding namespace
void f(int);
If this were included in the set of overloads within the scope of A, then suddenly the behaviour of A::g would change: it would call this instead of A::f. Restricting the overload set to names in the narrowest available scope prevents this kind of unexpected breakage.
As you (and your helpful compiler) say, the outer name is still available (with qualification) if you need it.
The compiler performs unqualified name lookup, for f, specified in §3.4.1 [basic.lookup.unqual] (thankfully, there's no ADL here):
1 In all the cases listed in 3.4.1, 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. If no
declaration is found, the program is ill-formed.
8 For the members of a class X, a name used in a member function
body, in a default argument, in an exception-specification, in the
brace-or-equal-initializer of a non-static data member (9.2), or in the definition of a class member outside of the definition of X,
following the member’s declarator-id, shall be declared in one of
the following ways:
before its use in the block in which it is used or in an enclosing block (6.3), or
shall be a member of class X or be a member of a base class of X (10.2), or
if X is a nested class of class Y (9.7), shall be a member of Y, or shall be a member of a base class of Y (this lookup applies
in turn to Y’s enclosing classes, starting with the innermost
enclosing class), or
if X is a local class (9.8) or is a nested class of a local class, before the definition of class X in a block enclosing the definition
of class X, or
if X is a member of namespace N, or is a nested class of a class that is a member of N, or is a local class or a nested class within
a local class of a function that is a member of N, before the use of
the name, in namespace N or in one of N’s enclosing namespaces.
Name lookup stops as soon as a declaration is found. So once it finds the member f() at the second bullet point it stops and never searches elsewhere.
Rejection of nonviable functions are done after name lookup, at overload resolution.
Why do I need to use :: to call the non-member function with the same name as the member function, but with different signature? What is the motivation for this requirement?
That is the whole point of having namespaces. A local (closer-scoped) name is preferred and more visible over a global name. Since a struct is again a scope, its f is shadowing the visibility of ::f. When you've to have the global one, you've to say you do. Why?
This is provided as a feature to make sure you can peacefully call functions you defined assuming they would get called, and when you need one from a different namespace, say the standard library, you'd state that explicitly, like std::. It's just a clean form of disambiguation, without leaving room for chance to play its part.
To understand the reason of your error and why you need to explicitly use the ::f() syntax, you may want to consider some aspects of the C++ compiler process:
The first thing the compiler does is name lookup.
Unqualified name lookup starts from the current scope, and then moves outwards; it stops as soon as it finds a declaration for the name of the function, even if this function will be later determined to not be a viable candidate for the function call.
Then, overload resolution is executed over the set of the functions that name lookup found.
(And, finally, access check is executed on the function that overload resolution picked up.)