0

Why is the reason of almost always, declare the ostream operator as a friend function, and not as a member function or as a free function? What benefits have to choose to implement it as a friend compared with the alternatives?

3

1 Answer 1

3

A member function doesn't work here, because it requires the lhs to be of the enclosing class type, while you need it to be ostream.

A free function would work, but it opens you up to some confusing overload resolution. A friend function behaves the same way regardless of whether caller is in the same namespace as the class (or has using namespace for it), because either way it can only be found via ADL. (I'm assuming the operator is in the same namespace as the class.)

But a free function can be found without ADL, but only if you're in the same namespace. When found without ADL, it can tolerate some implicit conversions of the rhs, which wouldn't work with ADL.

Example:

#include <iostream> struct AA {}; struct BB {}; namespace N { struct A { A(AA) {} template <typename T, typename U> friend std::basic_ostream<T,U> &operator<<(std::basic_ostream<T,U> &o, A) {return o;} }; struct B { B(BB) {} }; template <typename T, typename U> std::basic_ostream<T,U> &operator<<(std::basic_ostream<T,U> &o, B) {return o;} } int main() { { std::cout << AA{}; // error std::cout << BB{}; // error } { using namespace N; std::cout << AA{}; // error std::cout << BB{}; // ok } } 
Sign up to request clarification or add additional context in comments.

2 Comments

If I assume that there's no performance difference between the implementations, am I right?
@AlexVergara There's none.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.