简体   繁体   中英

Overloading of operator<< requiring const input argument for compilation

While compiling the below standard-code of overloaded ostream operator, a compilation error "error: no match for 'operator<<' (operand types are 'std::ostream' {aka 'std::basic_ostream'} and 'Digit')" is being returned for the post-fix increment console-out case.

It is clear that making the 2nd argument "const" solves the compilation error. Kindly check and explain why this is happening.

class Digit
{
private:
    int m_digit;
public:
    Digit(int digit=0)
        : m_digit{digit}
    {
    }

    Digit& operator++(); // prefix has no parameter
    Digit operator++(int); // postfix has an int parameter

    friend std::ostream& operator<< (std::ostream& out, /*const*/ Digit& d);
};

// No parameter means this is prefix operator++
Digit& Digit::operator++()
{
    // If our number is already at 9, wrap around to 0
    if (m_digit == 9)
        m_digit = 0;
    // otherwise just increment to next number
    else
        ++m_digit;

    return *this;
}

// int parameter means this is postfix operator++
Digit Digit::operator++(int)
{
    // Create a temporary variable with our current digit
    Digit temp{*this};

    // Use prefix operator to increment this digit
    ++(*this); // apply operator

    // return temporary result
    return temp; // return saved state
}


std::ostream& operator<< (std::ostream& out, /*const*/ Digit& d)   //-> works fine if const is uncommented
{
    out << d.m_digit;
    return out;
}

int main()
{
    Digit digit(5);

    std::cout << digit;
    std::cout << ++digit; // calls Digit::operator++();
    std::cout << digit++; // calls Digit::operator++(int);   //-> THIS LINE DOES NOT COMPILE
    std::cout << digit;

    return 0;
}

why this is happening.

Because the postfix version of overloaded operator++ returns by value which means that a call to Digit::operator++(int) is an rvalue which can't be bound to the nonconst lvalue reference parameter(named d ) of the overloaded operator<< and so the error.

Basically, ++digit is an lvalue expression which can be bound to a nonconst lvalue reference while digit++ is an rvalue expression which can't be bound to a nonconst lvalue reference.

To solve this we have to add a low-level const to the second parameter(named d ) as shown below:

//--------------------------------------------------vvvvv------------>adding const works because a const lvalue reference can be bound to an rvalue
friend std::ostream& operator<< (std::ostream& out, const Digit& d);

Adding a low-level const works because a const lvalue reference can be bound to an rvalue expression such as a call to Digit::operator++(int) . That is, even though digit++ is still an rvalue expression, it can now be bound to the modified const lvalue reference parameter named d .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM