An Optional!T and the implementation of the underlying type's opUnary

Simen Kjærås simen.kjaras at gmail.com
Thu Jul 26 06:37:41 UTC 2018


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


More information about the Digitalmars-d mailing list