3

I write a class Fraction, and would like to display Fraction object with std::cout:

Fraction f(3, 5);
std::cout << f << std::endl;

I know overloading operator << can be used for this display purpose. But I can also overload operator type() function, and when only with operator double()(let type be double), I can still std::cout << f << std::endl.

Even more, I can also implement operator std::string(). But, when the mentioned 3 overloaded operator functions all exist, without explicitly type conversion, which one is called when doing std::cout << f << std::endl ? This really makes me curious, is this undefined behavior denpending on compiler implementation, or if there is some rule for scoring the closest/most suitable function to call?

To reproduce, use the following code:

#include <iostream>
#include <string>

class Fraction
{
public:
    Fraction(int num, int den=1):
        numerator(num), denominator(den) {}
    
    operator double() const {
        std::cout << "[operator double()]";
        return numerator*1.0 / denominator;
    }

    operator std::string() const {
        std::cout << "[operator std::string()]";
        return std::to_string(numerator) + "/" + std::to_string(denominator);
    }

private:
    int numerator;
    int denominator;

#ifdef OVERLOAD_STREAM_OP
    friend std::ostream& operator << (std::ostream& os, const Fraction& frac);
#endif

};

#ifdef OVERLOAD_STREAM_OP
std::ostream& operator << (std::ostream& os, const Fraction& frac)
{
    std::cout << "[operator <<]";
    os << std::to_string(frac.numerator) << "/" << std::to_string(frac.denominator);
    return os;
}
#endif

int main()
{
    Fraction f(3, 5);
    double d = 4 + f;
    std::cout << "\n--- now let's print\n";
    std::cout << "f: " << f << std::endl;
    std::cout << "f: " << std::string(f) << std::endl;
    std::cout << d << std::endl;

    return 0;
}

The output on my ubuntu 20.04:

(base) zz@home% clang++ fraction.cpp
(base) zz@home% ./a.out 
[operator double()]
--- now let's print
f: [operator double()]0.6
f: [operator std::string()]3/5
4.6
4
  • 2
    If your class provides both an operator double() and an operator std::string(), the usage std::cout << f is a diagnosable error due to ambiguity, since both conversions of f are equally viable. This doesn't apply to 4 + f since there is no implicit conversion of std::string to int and no conversion of int to std::string but both operands 4 and f may be implicitly converted to double (and then added). The basic rule is that only one implicit conversion of any operand is permitted - and it is a diagnosable error if more than one conversion of any operand is possible. Commented Jun 5, 2021 at 5:05
  • @Peter I've tried again, if only provides operator std::string( ), then std::cout << f is not viable (at least with clang). Commented Jun 5, 2021 at 13:25
  • @ChrisZZ, Part of this strikes me as quite similar to a question I asked some time ago: stackoverflow.com/questions/17539555/… Commented Jun 5, 2021 at 15:33
  • @chris: I’d tend to say it’s a duplicate of that question, in that that answer explains this behavior (aside from some minor bits about +). Commented Jun 5, 2021 at 16:21

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.