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