1 /**
2     Optional compile time traits
3 */
4 module optional.traits;
5 
6 /// Checks if T is an optional type
7 template isOptional(T) {
8     import optional: Optional;
9     import std.traits: isInstanceOf;
10     enum isOptional = isInstanceOf!(Optional, T);
11 }
12 
13 ///
14 @("Example of isOptional")
15 unittest {
16     import optional: Optional;
17 
18     assert(isOptional!(Optional!int) == true);
19     assert(isOptional!int == false);
20     assert(isOptional!(int[]) == false);
21 }
22 
23 /// Returns the target type of a optional.
24 template OptionalTarget(T) if (isOptional!T) {
25     import std.traits: TemplateArgsOf;
26     alias OptionalTarget = TemplateArgsOf!T[0];
27 }
28 
29 ///
30 @("Example of OptionalTarget")
31 unittest {
32     import optional: Optional;
33 
34     class C {}
35     struct S {}
36 
37     import std.meta: AliasSeq;
38     foreach (T; AliasSeq!(int, int*, S, C, int[], S[], C[])) {
39         alias CT = const T;
40         alias IT = immutable T;
41         alias ST = shared T;
42 
43         static assert(is(OptionalTarget!(Optional!T) == T));
44         static assert(is(OptionalTarget!(Optional!CT) == CT));
45         static assert(is(OptionalTarget!(Optional!IT) == IT));
46         static assert(is(OptionalTarget!(Optional!ST) == ST));
47     }
48 }
49 
50 /// Checks if T is an optional chain
51 template isOptionalChain(T) {
52     import optional: OptionalChain;
53     import std.traits: isInstanceOf;
54     enum isOptionalChain = isInstanceOf!(OptionalChain, T);
55 }
56 
57 ///
58 @("Example of isOptionalChain")
59 @safe @nogc unittest {
60     import optional: oc, some;
61     static assert(isOptionalChain!(typeof(oc(some(3)))));
62 }