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 ) );