1 module nxt.array_traits;
2 
3 /// Is `true` iff `T` is a slice of `char`s.
4 enum isCharArray(T) = (is(T : const(char)[]));
5 
6 ///
7 @safe pure unittest
8 {
9     static assert(isCharArray!(char[]));
10     static assert(isCharArray!(const(char[])));
11     static assert(isCharArray!(const char[]));
12     static assert(isCharArray!(const const(char)[]));
13 
14     static assert(!isCharArray!(wstring));
15     static assert(!isCharArray!(dstring));
16 }
17 
18 /// Is `true` iff `T` is a slice of `char`s.
19 enum isArrayFast(T) = is(T : const(E)[], E);
20 
21 ///
22 @safe pure unittest
23 {
24     static assert(isArrayFast!(char[]));
25     static assert(isArrayFast!(int[]));
26     static assert(isArrayFast!(const(char[])));
27     static assert(isArrayFast!(const char[]));
28     static assert(isArrayFast!(const const(char)[]));
29     static assert(isArrayFast!(string[]));
30     static assert(isArrayFast!(immutable(int)[]));
31     static assert(isArrayFast!(char[3]));
32 }
33 
34 /// Is `true` iff `T` is a slice of `char`s.
35 enum isDynamicArrayFast(T) = is(T : const(E)[], E) && !__traits(isStaticArray, T);
36 
37 ///
38 @safe pure unittest
39 {
40     static assert(isDynamicArrayFast!(char[]));
41     static assert(isDynamicArrayFast!(int[]));
42     static assert(isDynamicArrayFast!(const(char[])));
43     static assert(isDynamicArrayFast!(const char[]));
44     static assert(isDynamicArrayFast!(const const(char)[]));
45     static assert(isDynamicArrayFast!(string[]));
46     static assert(isDynamicArrayFast!(immutable(int)[]));
47     static assert(!isDynamicArrayFast!(char[3]));
48 }
49 
50 /** Is `true` iff all `Ts` are slices with same unqualified matching element types.
51  *
52  * Used to define template-restrictions on template parameters of only arrays
53  * (slices) of the same unqualified element types.
54  */
55 template isSameSlices(Ts...)
56 if (Ts.length >= 2)
57 {
58     enum isSlice(T) = is(T : const(E)[], E);
59     enum isSliceOf(T, E) = is(T : const(E)[]);
60     static if (isSlice!(Ts[0]))
61     {
62         alias E = typeof(Ts[0].init[0]);
63         static foreach (T; Ts[1 .. $])
64         {
65             static if (is(typeof(isSameSlices) == void) && // not yet defined
66                        !(isSliceOf!(T, E)))
67             {
68                 enum isSameSlices = false;
69             }
70         }
71         static if (is(typeof(isSameSlices) == void)) // if not yet defined
72         {
73             enum isSameSlices = true;
74         }
75     }
76     else
77     {
78         enum isSameSlices = false;
79     }
80 }
81 
82 ///
83 @safe pure unittest
84 {
85     static assert(isSameSlices!(int[], int[]));
86     static assert(isSameSlices!(const(int)[], int[]));
87     static assert(isSameSlices!(int[], const(int)[]));
88     static assert(isSameSlices!(int[], immutable(int)[]));
89 
90     static assert(isSameSlices!(int[], int[], int[]));
91     static assert(isSameSlices!(int[], const(int)[], int[]));
92     static assert(isSameSlices!(int[], const(int)[], immutable(int)[]));
93     static assert(isSameSlices!(const(int)[], const(int)[], const(int)[]));
94 
95     static assert(!isSameSlices!(int, char));
96     static assert(!isSameSlices!(int, const(char)));
97     static assert(!isSameSlices!(int, int));
98 
99     static assert(!isSameSlices!(int[], char[]));
100     static assert(!isSameSlices!(int[], char[], char[]));
101     static assert(!isSameSlices!(char[], int[]));
102 
103     static assert(!isSameSlices!(char[], dchar[]));
104     static assert(!isSameSlices!(wchar[], dchar[]));
105     static assert(!isSameSlices!(char[], wchar[]));
106 }