Search code examples
c++operator-overloadingoverload-resolution

How to prefer `operator<<` over generic `operator T()` conversion?


When both an operator <<(std::ostream&... and a generic conversion operator template<typename T> operator T() are defined, std::cout << foo(); is ambiguous. Is there a way to make that resolve to invoking operator <<?

Shortest working code:

#include<iostream>

struct foo {
    int x;
    template<typename T> operator T() { return static_cast<T>(x); }
    friend std::ostream& operator <<(std::ostream& out, foo& f) { return out << f.x; }
};

//std::ostream& operator <<(std::ostream& out, foo& f) { return out << f.x; } // doesn't help

int main() {
    std::cout << foo() << std::endl;
    return 0;
}

Solution

  • Your own operator is not viable as it takes the foo by non-const ref which the temporary cannot bind to. Thus, the post-conversion overloads are considered in the first place.

    Changing its declaration to

    friend std::ostream& operator <<(std::ostream& out, const foo& f) { return out << f.x; }
    

    fixes the issue. Now your operator is the better match as it requires no conversion.