Joe Smith
Joe Smith

Reputation: 127

How does the C++ compiler find operator overloading?

I have been looking into examples of operator overloading and some will include code snippets such as

ostream& operator<<(ostream& os, const Date& dt)
{
    os << dt.mo << '/' << dt.da << '/' << dt.yr;
    return os;
}

The ostream& operator<<(ostream& os, ...) seems to placed, for what atleast seems "randomly" around a C++ program. My question is, can it be placed anywhere? How does the C++ find, compile and now interpret overloading << for the class Date to now return a ostream& and use this function.

Upvotes: 1

Views: 374

Answers (3)

Ralf Ulrich
Ralf Ulrich

Reputation: 1714

This is ADL, argument-dependent-lookup, see e.g. https://en.cppreference.com/w/cpp/language/adl

For example, typically all the standard operator<<(std::ostream&, ...) are defined in std:: namespace, they don't exist in global namespace. So, why does code like std::cout << "Hi there"; work, where the operator is not explicitly namepaced?

Only with ADL the compiler will search and find them in std, because of the location of cout / ostream / etc in the namespace std. Thus, when you write new operators, make sure ADL will find them -- without polluting the global namespace.

This is true for all function name lookups, operator overloading is just a special case for this.

Upvotes: 1

Ashutosh Raghuwanshi
Ashutosh Raghuwanshi

Reputation: 440

A very sort answer could be the scope of the operator function defines the places where it will be effective.

How to control the scope of a function/method is out of the scope of this question. (pun intended)

Upvotes: 1

user8143588
user8143588

Reputation:

You can simply define as an inline as you did

std::ostream& operator << ( ostream& os, const Date& dt ) {
    os << dt.mo << '/' << dt.da << '/' << dt.yr;
    return os;
}

But you have to include this header before you use it, otherwise the C++ compiler will not know.

Or you can define as a friend inline inside the class, which will allow you to tap into private and protected fields, for example if the "mo", "da" and "yr" fields were private inside Date.

class Date { 
...
    friend inline std::ostream& operator << ( ostream& os, const Date& dt ) {
        os << dt.mo << '/' << dt.da << '/' << dt.yr;
        return os;
    }
};

or you can define in the header (Date.h)

class Date { 
...
    friend std::ostream& operator << ( ostream& os, const Date& dt );
};

and then implement in the body (Date.cpp) file

std::ostream& operator << ( ostream& os, const Date& dt ) {
    os << dt.mo << '/' << dt.da << '/' << dt.yr;
    return os;
}

Upvotes: 1

Related Questions