1 /**
2 * The tuple module defines a template struct used for arbitrary data grouping.
3 *
4 * Copyright:
5 * Copyright (C) 2005-2006 Sean Kelly.
6 * Some parts copyright (c) 2009-2016 dunnhumby Germany GmbH.
7 * All rights reserved.
8 *
9 * License:
10 * Tango Dual License: 3-Clause BSD License / Academic Free License v3.0.
11 * See LICENSE_TANGO.txt for details.
12 *
13 * Authors: Walter Bright, Sean Kelly
14 *
15 */
16 module ocean.core.Tuple;
17
18
19 /**
20 * A Tuple is a an aggregate of typed values. Tuples are useful for returning
21 * a set of values from a function or for passing a set of parameters to a
22 * function.
23 *
24 * NOTE: Since the transition from user-defined to built-in tuples, the ability
25 * to return tuples from a function has been lost. Until this issue is
26 * addressed within the language, tuples must be enclosed in a struct
27 * if they are to be returned from a function.
28 *
29 * Example:
30 * ----------------------------------------------------------------------
31 * alias Tuple!(int, real) T1;
32 * alias Tuple!(int, long) T2;
33 * struct Wrap( Vals... )
34 * {
35 * Vals val;
36 * }
37 *
38 * Wrap!(T2) func( T1 val )
39 * {
40 * Wrap!(T2) ret;
41 * ret.val[0] = val[0];
42 * ret.val[1] = val[0] * cast(long) val[1];
43 * return ret;
44 * }
45 * ----------------------------------------------------------------------
46 *
47 * This is the original tuple example, and demonstates what should be possible
48 * with tuples. Hopefully, language support will be added for this feature
49 * soon.
50 *
51 * Example:
52 * ----------------------------------------------------------------------
53 * alias Tuple!(int, real) T1;
54 * alias Tuple!(int, long) T2;
55 *
56 * T2 func( T1 val )
57 * {
58 * T2 ret;
59 * ret[0] = val[0];
60 * ret[1] = val[0] * cast(long) val[1];
61 * return ret;
62 * }
63 *
64 *
65 * // tuples may be composed
66 * alias Tuple!(int) IntTuple;
67 * alias Tuple!(IntTuple, long) RetTuple;
68 *
69 * // tuples are equivalent to a set of function parameters of the same type
70 * RetTuple t = func( 1, 2.3 );
71 * ----------------------------------------------------------------------
72 */
73 template Tuple( TList... )
74 {
75 alias TList Tuple;
76 }
77
78
79 /**
80 * Returns the index of the first occurrence of T in TList or Tlist.length if
81 * not found.
82 */
83 template IndexOf( T, TList... )
84 {
85 static if( TList.length == 0 )
86 static immutable size_t IndexOf = 0;
87 else static if( is( T == TList[0] ) )
88 static immutable size_t IndexOf = 0;
89 else
90 static immutable size_t IndexOf = 1 + IndexOf!( T, TList[1 .. $] );
91 }
92
93
94 /**
95 * Returns a Tuple with the first occurrence of T removed from TList.
96 */
97 template Remove( T, TList... )
98 {
99 static if( TList.length == 0 )
100 alias TList Remove;
101 else static if( is( T == TList[0] ) )
102 alias TList[1 .. $] Remove;
103 else
104 alias Tuple!( TList[0], Remove!( T, TList[1 .. $] ) ) Remove;
105 }
106
107
108 /**
109 * Returns a Tuple with all occurrences of T removed from TList.
110 */
111 template RemoveAll( T, TList... )
112 {
113 static if( TList.length == 0 )
114 alias TList RemoveAll;
115 else static if( is( T == TList[0] ) )
116 alias .RemoveAll!( T, TList[1 .. $] ) RemoveAll;
117 else
118 alias Tuple!( TList[0], .RemoveAll!( T, TList[1 .. $] ) ) RemoveAll;
119 }
120
121
122 /**
123 * Returns a Tuple with the first offuccrence of T replaced with U.
124 */
125 template Replace( T, U, TList... )
126 {
127 static if( TList.length == 0 )
128 alias TList Replace;
129 else static if( is( T == TList[0] ) )
130 alias Tuple!(U, TList[1 .. $]) Replace;
131 else
132 alias Tuple!( TList[0], Replace!( T, U, TList[1 .. $] ) ) Replace;
133 }
134
135
136 /**
137 * Returns a Tuple with all occurrences of T replaced with U.
138 */
139 template ReplaceAll( T, U, TList... )
140 {
141 static if( TList.length == 0 )
142 alias TList ReplaceAll;
143 else static if( is( T == TList[0] ) )
144 alias Tuple!( U, ReplaceAll!( T, U, TList[1 .. $] ) ) ReplaceAll;
145 else
146 alias Tuple!( TList[0], ReplaceAll!( T, U, TList[1 .. $] ) ) ReplaceAll;
147 }
148
149
150 /**
151 * Returns a Tuple with the types from TList declared in reverse order.
152 */
153 template Reverse( TList... )
154 {
155 static if( TList.length == 0 )
156 alias TList Reverse;
157 else
158 alias Tuple!( Reverse!( TList[1 .. $]), TList[0] ) Reverse;
159 }
160
161
162 /**
163 * Returns a Tuple with all duplicate types removed.
164 */
165 template Unique( TList... )
166 {
167 static if( TList.length == 0 )
168 alias TList Unique;
169 else
170 alias Tuple!( TList[0],
171 Unique!( RemoveAll!( TList[0],
172 TList[1 .. $] ) ) ) Unique;
173 }
174
175
176 /**
177 * Returns the type from TList that is the most derived from T. If no such
178 * type is found then T will be returned.
179 */
180 template MostDerived( T, TList... )
181 {
182 static if( TList.length == 0 )
183 alias T MostDerived;
184 else static if( is( TList[0] : T ) )
185 alias MostDerived!( TList[0], TList[1 .. $] ) MostDerived;
186 else
187 alias MostDerived!( T, TList[1 .. $] ) MostDerived;
188 }
189
190
191 /**
192 * Returns a Tuple with the types sorted so that the most derived types are
193 * ordered before the remaining types.
194 */
195 template DerivedToFront( TList... )
196 {
197 static if( TList.length == 0 )
198 alias TList DerivedToFront;
199 else
200 alias Tuple!( MostDerived!( TList[0], TList[1 .. $] ),
201 DerivedToFront!( ReplaceAll!( MostDerived!( TList[0], TList[1 .. $] ),
202 TList[0],
203 TList[1 .. $] ) ) ) DerivedToFront;
204 }
205
206
207 /*
208 * A brief test of the above templates.
209 */
210 static assert( 0 == IndexOf!(int, int, float, char));
211 static assert( 1 == IndexOf!(float, int, float, char));
212 static assert( 3 == IndexOf!(double, int, float, char));
213
214 static assert( is( Remove!(int, int, float, int) == Remove!(void, float, int) ) );
215 static assert( is( RemoveAll!(int, int, float, int) == Remove!(void, float) ) );
216 static assert( is( Remove!(float, int, float, int) == Remove!(void, int, int) ) );
217 static assert( is( Remove!(double, int, float, int) == Remove!(void, int, float, int) ) );
218
219 static assert( is( Replace!(int, char, int, float, int) == Remove!(void, char, float, int) ) );
220 static assert( is( ReplaceAll!(int, char, int, float, int) == Remove!(void, char, float, char) ) );
221 static assert( is( Replace!(float, char, int, float, int) == Remove!(void, int, char, int) ) );
222 static assert( is( Replace!(double, char, int, float, int) == Remove!(void, int, float, int) ) );
223
224 static assert( is( Reverse!(float, float[], double, char, int) ==
225 Unique!(int, char, double, float[], char, int, float, double) ) );
226
227 static assert( is( MostDerived!(int, long, short) == short ) );