C++ allows for overloading type casts by creating an operator T()
where T
is the type we want to cast to.
Now, how does this feature play together with references? For example:
struct Y{ int i; };
struct X{
Y y;
operator Y() const { return y; }
};
Here, we can cast an X
to Y
which will simply return the contained Y
. But what if we want to make a cast to an Y
reference. For example, C++ allows us to do this:
struct X{
Y y;
operator Y&(){ return y; }
operator const Y&() const { return y; }
};
Now, we can cast an X
to a Y
reference or a const
reference (which also works for a const X
).
Is there any difference in the semantics of the first and the second example? What is the best way if I want to allow casting to a reference?
I could imagine that even if I write operator T()
without any &
, C++ might allow that the cast returns a result by reference (i.e., it might somehow add implicit operator T&()
methods when I specify operator T()
).
For example, I want the following code to work:
int main(){
X x;
Y& y = x; // y now references the y inside x
y.i = 5;
std::cout << x.y.i << std::endl; // Should print 5 now
}
What is the most simple way to achieve this?
You would want an expression, a + b , to return a reference to one of a or b, which would have the results of the expression. Thus you would modify one of a or b to be the sum of a and b. So you would want to redefine the semantics of the operator (+) to be the same as the operator (+=).
Cast operator () In C, the result of the cast operation is not an lvalue. In C++, the cast result belongs to one of the following value categories: If type is an lvalue reference type. or an rvalue reference to a function type.
Here, + is a binary operator that works on the operands num and 9 . When we overload the binary operator for user-defined types by using the code: obj3 = obj1 + obj2; The operator function is called using the obj1 object and obj2 is passed as an argument to the function.
C does not support operator overloading (beyond what it built into the language).
Does declaring a
operator T()
imply that the cast always returns aT
by value?
Yes.
The return type of conversion operators is implicitly exactly what they convert to.
[...] the type of the conversion function is “function taking no parameter returning conversion-type-id”.
§12.3.2 [class.conv.fct]
With clang++:
#include <iostream>
class test
{
public:
test(int n) : nb{n} {}
public:
operator int() { return nb; }
private:
int nb;
};
int main(void)
{
test t{42};
int x = t;
int& ref = t; // error: non-const lvalue reference to type 'int' cannot bind to a value of unrelated type 'test'
int&& rref = t; // compiles fine
std::cout << x << std::endl;
}
Which suggest that you do return a temporary new value.
The real question to help you choose between your two cases is: do you want to let people modify your internal member (return a reference) and is that member expensive to copy (use a const reference instead of value) ?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With