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.