1 module meta_ex;
2 
3 import std.range : isInputRange;
4 import std.meta : NoDuplicates, AliasSeq;
5 
6 static if (__VERSION__ >= 2070)
7 {
8     import std.meta : aliasSeqOf;
9 }
10 else
11 {
12     /** Create $(D AliasSeq) from Static Array.
13         See also: http://forum.dlang.org/thread/cxahuyvnygtpsaseieeh@forum.dlang.org
14         See also: https://github.com/D-Programming-Language/phobos/pull/3785
15     */
16     template aliasSeqOf(TL...)
17         if (TL.length == 1 &&
18             isInputRange!(typeof(TL[0])))
19     {
20         import std.range: front, empty, popFront;
21         alias TT = AliasSeq;
22         enum r = TL[0];
23         static if (r.empty)
24         {
25             alias aliasSeqOf = TT!();
26         }
27         else
28         {
29             enum f = r.front;
30             alias aliasSeqOf = TT!(
31                 f,
32                 aliasSeqOf!(
33                     { auto tmp = r; tmp.popFront(); return tmp; }()
34                     )
35                                    );
36         }
37     }
38 }
39 
40 alias toAliasSeq = aliasSeqOf;
41 
42 @safe pure nothrow @nogc unittest
43 {
44     import std.range : iota;
45     foreach(i; aliasSeqOf!(iota(10)))
46     {
47         // pragma(msg, i);
48     }
49 }
50 
51 alias Deduplicate = NoDuplicates;
52 alias Uniq = NoDuplicates;
53 
54 /**
55    See also: http://forum.dlang.org/post/sulxqtfprmkeekjatqup@forum.dlang.org
56 */
57 template Merge1(A...)
58     if (!(A.length & 1))
59 {
60     static if (A.length == 0)
61     {
62         alias Merge1 = AliasSeq!();
63     }
64     else
65     {
66         alias Left = A[0 .. $ / 2];
67         alias Right = A[$ / 2 .. $];
68         alias Merge1 = AliasSeq!(Left[0], Right[0], Merge1!(Left[1 .. $], Right[1 .. $]));
69     }
70 }
71 
72 @safe pure nothrow @nogc unittest
73 {
74     struct S(A...) {} // needed to reliably compare AliasSeq's for equality
75 
76     alias first = AliasSeq!(int, string, bool);
77     alias second = AliasSeq!("abc", "def", "ghi");
78     alias third = Merge1!(first, second);
79 
80     static assert(is(S!third == S!(int,    "abc",
81                                    string, "def",
82                                    bool,   "ghi")));
83 }
84 
85 /**
86    See also: http://forum.dlang.org/post/sulxqtfprmkeekjatqup@forum.dlang.org
87 */
88 template Merge(A...)
89 {
90     template With(B...)
91     {
92         static if (A.length == 0 ||
93                    B.length == 0)
94             alias With = AliasSeq!(A, B); // or static assert(0) if you require equal lengths
95         else
96             alias With = AliasSeq!(A[0], B[0], Merge!(A[1 .. $]).With!(B[1 .. $]));
97     }
98 }
99 
100 @safe pure nothrow @nogc unittest
101 {
102     struct S(A...) {} // needed to reliably compare AliasSeq's for equality
103 
104     alias first = AliasSeq!(int, string, bool);
105     alias second = AliasSeq!("abc", "def", "ghi");
106     alias third = Merge!first.With!second;
107 
108     static assert(is(S!third == S!(int, "abc",
109                                    string, "def",
110                                    bool, "ghi")));
111 
112     alias fourth = Merge!(first[0 .. 2]).With!second;
113 
114     static assert(is(S!fourth == S!(int, "abc",
115                                     string, "def",
116                                     "ghi")));
117 }