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