Search code examples
c++operator-overloadingmember-functionsoverload-resolution

Order of operator overload resolution involving temporaries


Consider the following minimal example:

#include <iostream>

using namespace std;

class myostream : public ostream {
    public:
        myostream(ostream const &other) :
            ostream(other.rdbuf())
        { }
};

int main() {
    cout << "hello world" << endl;

    myostream s(cout);
    s << "hello world" << endl;

    myostream(cout) << "hello world" << endl;
}

The output, both on g++ and on Visual C++, is

hello world
hello world
0x4012a4

The version that writes to a temporary object, myostream(cout), appears to prefer the member operator ostream::operator<<(void *), instead of the free operator operator<<(ostream &, char *). It seems to make a difference whether or not the object has a name.

Why does this happen? And how do I prevent this behaviour?

Edit: Why it happens is now clear from various answers. As to how to prevent this, the following seems appealing:

class myostream : public ostream {
    public:
        // ...
        myostream &operator<<(char const *str) {
            std::operator<<(*this, str);
            return *this;
        }
};

However, this results in all kinds of ambiguities.


Solution

  • rvalues can't be bound to non-const reference. So in your example the temporary of type ostream can't be the first argument of free operator<<(std::ostream&, char const*) and what is used is the member operator<<(void*).

    If you need it, you can add a call such as

    myostream(cout).flush() << "foo";
    

    which will transform the rvalue into a reference.

    Note that in C++0X, the introduction of rvalue reference will allow to provide overload of operator<< taking rvalue references as parameter, solving the root cause of the issue.