Home > Software engineering >  Does member function like operator<< , operator* need ADL to work?
Does member function like operator<< , operator* need ADL to work?

Time:02-20

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.

  • Related