Reputation: 1479
union word{
uint16_t value;
struct{
uint8_t low;
uint8_t high;
};
inline word(uint16_t value) noexcept
:value(value)
{}
inline word &operator=(uint16_t rhs) noexcept{
value = rhs;
return *this;
}
inline operator uint16_t() const noexcept{
return value;
}
}
I am trying to define a little endian 2 byte type where it is easy to access the low and high byte. In addition, I want the "word" type to act completely like a uint16_t when calling any arithmetic operator. Hence, I have overloaded the typecast operator for uint16_t.
But I have run into a slight problem:
word w1 = 5;
w1 = w1 + w1; //this works fine due to implicit conversion
w1 += w1; //fails to compile. lhs will not implicitly convert
I understand why it fails to compile. I'd like to have to avoid overloading all of the arithmetic operators such as +=, -=, &=, |=, etc. Is there anyway to avoid having to define all of the operators? It is likely I will need most of them.
Thank you very much!
Upvotes: 2
Views: 167
Reputation: 17708
The problem is with this line:
inline operator uint16_t() const noexcept{
return value;
}
When you do
w1 += w1;
the left hand w1
is implicitly converted to a uint16_t
. However, you are actually returning a copy of w1.value
which, as a result of the conversion, is a temporary object. And you are not allowed to assign to a temporary object. And if you magically can, the changes will not reflect to w1.value
, something you do not want.
To solve your problem, return a reference of value
instead, and make the conversion function not const
, as you would absolutely want value
to be modifiable.
inline operator uint16_t&() noexcept{
return value;
}
Here is a live example showing that the solution works.
However, I recommend you to read this question: Operator overloading
Explicitly overloading the operators of your class would be much safer and predictable than relying on implicit conversions, which sometimes would yield weird results and compile errors.
Upvotes: 1