On Wednesday, 25 July 2018 at 21:59:00 UTC, aliak wrote:
It needs to work with const as well and immutable too.
immutable a = 3;
auto b = -a; // is ok, should be ok with the optional as well.
Plus T can be a custom type as well with "some" definition of
opUnary. I can't seem to find any implementation guidelines
either so I assume opUnary or any of the ops implementation
details is implementation defined.
Template this[0] (and CopyTypeQualifiers[1])to the rescue!
import std.traits: isPointer, CopyTypeQualifiers;
auto opUnary(string op, this This)()
if (__traits(compiles, (CopyTypeQualifiers!(This, T) t){
mixin("return "~op~"t;"); }))
{
alias U = CopyTypeQualifiers!(This, T);
static if (op == "*" && isPointer!T) {
import std.traits: PointerTarget;
alias P = PointerTarget!U;
return empty || front is null ? no!P :
some(cast(P)*this._value);
} else {
if (empty) {
return no!U;
} else {
return some(mixin(op ~ "cast(U)_value"));
}
}
}
unittest {
Optional!int a;
++a;
auto a2 = -a;
assert(!a2._hasValue);
a = some(3);
a++;
immutable b = Optional!int(3);
static assert(!__traits(compiles, ++b));
auto b2 = -b;
}
As for assigning to Optional!(immutable int), the language
basically forbids this (cannot modify struct with immutable
members). It would, as you say, cause problems when you can get a
pointer to the contents.
[0]: https://dlang.org/spec/template.html#template_this_parameter
[1]: https://dlang.org/phobos/std_traits#CopyTypeQualifiers
--
Simen