Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lvalue reference operator vs assignment operator precedence

I came across a compilation error in which I was hoping the compiler would implicitly use a custom lvalue reference operator rather than an assignment operator.

I have generated a minimum reproducible example that shows the phenomenon. Could someone explain what is happening here and potentially ways to allow the implicit lvalue reference operator to be called?

If I uncomment the assignment operator deletion this fails to compile:

#include <iostream>

template <typename T>
struct wrapper
{
private:
    T t;
public:
    wrapper( T _t ) : t( _t ) {}
//    wrapper<T> operator=( T ) = delete;
    operator const T&() const { return t; }
    operator T&() { return t; }
};

int main()
{
    wrapper<int> w( 0 );

    std::cout << w << std::endl;
    w = 1;
    std::cout << w << std::endl;
}
like image 442
ryan.walton.256 Avatar asked Apr 12 '26 08:04

ryan.walton.256


1 Answers

But even if operator= is commented, w = 1 is not calling either operator [const] T&. It is simply using the wrapper(T) constructor to make a wrapper out of 1, and then the implicitly defined operator= to assign that value to w. If you delete operator=, that's clearly not possible.

The operator T& is being used only by the cout line, because it is an operator that can convert a wrapper (for which you have not overloaded <<) to something that << can deal with, an int.

I guess you wanted w = 1; to implicitly behave as if it was static_cast<int&>(w) = 1;.


The one above, by itself, is an incomplete answer, as the whole point is probably why doesn't w = 1; behave like static_cast<int&>(w) = 1;? And the answer is that operator= is special, as suggested in the answer linked in a comment by Artyer. The relevant wording in the standard is here.

like image 119
Enlico Avatar answered Apr 13 '26 22:04

Enlico



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!