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

Reply via email to