Olive's answer is correct, because in this case the standard seems quite understandable. The solution I chose at the same time was to leave only one conversion statement:
operator const std::string& () const&
The problem exists because both conversion operators are considered viable. Therefore, this can be avoided by changing the type of the implicit argument of the lvalue conversion operator from const & to & :
operator const std::string& () &
But this interrupts the conversion from const StringDecorator , which makes its use inconvenient in typical cases.
This broken decision made me wonder if there was a way to specify a member function specifier that would make the conversion statement viable with a const lvalue object, but not with an rvalue. And I managed to achieve this by specifying an implicit argument for the const conversion operator as const volatile & :
operator const std::string& () const volatile&
Per [dcl.init.ref] / 5 , for a link to be initialized by linking to rvalue, the link must be a constant of a non-volatile lvalue link or a rvalue link:
While the lvalue reference and the const lvalue reference can communicate with the volatile reference constant. Obviously, the mutable modifier of a member function performs a completely different task. But hey, this works and is enough for my use. The only remaining problem is that the code becomes misleading and awesome.
source share