1 ///
2 module dpq.meta;
3
4 import dpq.attributes;
5
6 import std.traits;
7 import std.typecons : Nullable;
8 import std.datetime : SysTime;
9
10 version(unittest) import std.stdio;
11
12 /**
13 Returns the array's base type
14
15 Returns the string type for any type that returns true
16 for isSomeString!T
17
18 Examples:
19 ---------------
20 alias T = BaseType!(int[][]);
21 alias T2 = BaseType!(int[]);
22 alias T3 = BaseType!int;
23 alias T4 = BaseType!(string[])
24
25 static assert(is(T == int));
26 static assert(is(T2 == int));
27 static assert(is(T3 == int));
28 static assert(is(T4 == string));
29 ---------------
30 */
31 template BaseType(T)
32 {
33 import std.typecons : TypedefType;
34 static if (isArray!T && !isSomeString!T)
35 alias BaseType = BaseType!(ForeachType!T);
36 else
37 alias BaseType = TypedefType!(Unqual!T);
38 }
39
40 unittest
41 {
42 writeln(" * meta");
43 writeln("\t * BaseType");
44
45 static assert(is(BaseType!(int[][][]) == int));
46 static assert(is(BaseType!(string[]) == string));
47 static assert(is(BaseType!string == string));
48 static assert(is(BaseType!dstring == dstring));
49 }
50
51 /**
52 Returns the number of dimensions of the given array type
53
54 Examples:
55 -----------------
56 auto dims = ArrayDimensions!(int[][]);
57 static assert(dims == 2);
58 -----------------
59 */
60 deprecated("Use ArraySerialier's ArrayDimensions instead")
61 template ArrayDimensions(T)
62 {
63 static if (isArray!T)
64 enum ArrayDimensions = 1 + ArrayDimensions!(ForeachType!T);
65 else
66 enum ArrayDimensions = 0;
67 }
68
69
70 /// Removes any Nullable specifiers, even multiple levels
71 template NoNullable(T)
72 {
73 static if (isInstanceOf!(Nullable, T))
74 // Nullable nullable? Costs us nothing, so why not
75 alias NoNullable = NoNullable!(Unqual!(ReturnType!(T.get)));
76 else
77 alias NoNullable = T;
78 }
79
80 /**
81 Will strip off any Nullable, Typedefs and qualifiers from a given type.
82 It's a bit paranoid and tries to remove any identifiers multiple times, until
83 the removal attempt yields no changes, but it shouldn't be a problem since it's
84 all just compile-time.
85
86 Examples:
87 static assert(RealType!(const Nullable!(immutable int) == int));
88 */
89 template RealType(T)
90 {
91 import std.typecons : TypedefType;
92 // Ugly, but better than doing this every time we need it
93 alias NT = OriginalType!(Unqual!(NoNullable!(TypedefType!T)));
94
95 static if (is(T == NT))
96 alias RealType = NT;
97 else
98 alias RealType = RealType!NT;
99 }