I have a code snippet (Hypothetically):
#include <iostream>
struct Pirate {
void song_name() {
std::cout << "Bink's Sake\n";
}
Pirate& operator*(Pirate const& other) {
// do something
return *this;
}
};
int main() {
Pirate p1{} p2{};
p1.song_name(); // does this use qualified or unqualifed name lookup?
p1 * p2;
std::cout << 5;
std::cout << 'a';
}
Does p1 * p2
use qualified name lookup or unqualified name lookup or ADL?
std::cout << 5
transforms into std::cout.operator<<(5);
std::cout << 'a'
transforms into std::operator<<(std::cout, 'a');
Does member functions require ADL to work? Does the above two statments use qualified or unqualifed name lookup or ADL?
Thanks
CodePudding user response:
The operators lookup non-static member functions like
std::cout.operator<<(5);
but also non-member functions via unqualified lookup and ADL if they have a non-member variant. All of these together form the overload set.
For this to work correctly non-member variants should be found via ADL, i.e. placed inside the namespace of the class for which they are overloading the operator. E.g. for overloading operator<<
for your own classes you cannot use a member version, because the first argument is probably supposed to be anything derived from std::ostream
. Then ADL on the non-member variant is the only way to make it work everywhere.
CodePudding user response:
A name is a qualified name if the scope to which it belongs is explicitly denoted using a scope-resolution operator (::
) or a member access operator (.
or ->
).
Case 1
Thus, when you wrote:
p1.song_name(); //here p1.song_name is a qualified name
In the above statement, p1.song_name
is a qualified name and so here qualified lookup takes place.
Case 2
Next, when your wrote:
p1 * p2;
The above statement is equivalent to:
p1.operator*(p2);
Since your class Pirate
have an overloaded member function operator*
, the above statement will use that member function. The above statement uses qualified lookup as well because we have used the member access operator .
.
Case 3
Here we have the statement:
std::cout << 5;
The above statement is equivalent to:
std::cout.operator<<(5);
which uses qualified lookup since it has member access operator .
Case 4
Here we look at the statement:
operator<<(std::cout, 'a');
Here the char
overload from operator<<
for ofstream
is used. This uses ADL because in this case the first parameter has a class type. So the compiler will also look in the namespace in which cout
is defined. Thus, for this call, the compiler also looks in the std
namespace and finds the char
overload.