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