/** * Authors: Tomoya Tanjo * Copyright: © 2021 Tomoya Tanjo * License: Apache-2.0 */ module salad.type; public import sumtype; import std.meta : allSatisfy, anySatisfy, templateNot; struct None{} private enum isNone(T) = is(T == None); template Optional(TS...) if (allSatisfy!(templateNot!isNone, TS)) { alias Optional = SumType!(None, TS); } enum isOptional(T) = isSumType!T && is(T.Types[0] == None) && allSatisfy!(templateNot!isNone, T.Types[1..$]); // test for Optional!T @safe unittest { import std.exception : assertNotThrown; auto op = Optional!int.init; op.tryMatch!((None _) {}) .assertNotThrown; } // TODO: more appropriate name template Either(TS...) if (allSatisfy!(templateNot!isNone, TS)) { alias Either = SumType!TS; } enum isEither(T) = isSumType!T && allSatisfy!(templateNot!isNone, T.Types); @safe unittest { static assert(isEither!(SumType!(int, string, double))); static assert(!isEither!(Optional!int)); static assert(isEither!(SumType!(int, string))); static assert(!isEither!(SumType!(None, int, string))); static assert(!isEither!string); }