Reputation: 6835
struct Type
{
auto opBinary(string op)(Type other) const {
return Type(); // #1 return type is Type
return typeof(this)(); // #2 return type is const(Type)
}
}
unittest
{
Type t1, t2;
auto t3 = t1 + t2;
}
In t1.opBinary!("+")(t2)
, t1
becomes a const, while t2
stays non-const. Should opBinary
's return type be Type
or const(Type)
, and why?
const(T)
is a supertype, so maybe it should return a const
, but I've hardly seen this in practice. Things also become rather complicated when dealing with a hierarchy of types and functions that use those types or are used by those types.
Upvotes: 0
Views: 139
Reputation: 3803
Should return type be T or const(T)? Any will do.
Which one is better? Depends on your intended behavior.
const qualifier on opBinary only means that hidden "this" argument is const. Nothing more, nothing else. It does not imply anything about the return type. It all boils down to pretty simple choice:
struct Type
{
int a;
auto opBinary(string op)(Type other) const
if (op == "+")
{
return Type(this.a + other.a);
}
}
void main()
{
Type first, second;
(first + second).a = 42; // Do you want to allow this?
// Yes -> return non-const
// No -> return const
}
If you want to preserve qualifiers of arguments, use either inout (see Adams answer) or manual check for qualifiers for more complicated choices.
With either choice remember automatic type deduction:
auto third = first + second;
third.a = 42; // Error if returns const
Type fourth = first + second;
fourth.a = 42; // Fine in both cases, struct was copied
In the end it is about you intention as a type designer how class/struct should behave.
Upvotes: 1
Reputation: 25595
Since the return value here is a new object, I'd say make it non-const. Being new, it can be modified safely, so no reason to unnecessarily restrict it with const.
If you were returning a part of the existing object, you'll want to use inout instead of const. inout means the constness of the object will also go to the return value.
inout(Type) opBinary(string op)(Type other) inout {
return whatever;
}
Now if you use a const(Type) object, the return will be const as well, and if it is called on a mutable object, the return is also mutable.
Upvotes: 4