Expand Up
@@ -3,9 +3,9 @@
/**
* Templates to manipulate template argument lists (also known as type lists).
*
* Some operations on type tuples are built in to the language,
* Some operations on alias sequences are built in to the language,
* such as TL[$(I n)] which gets the $(I n)th type from the
* type tuple . TL[$(I lwr) .. $(I upr)] returns a new type
* alias sequence . TL[$(I lwr) .. $(I upr)] returns a new type
* list that is a slice of the old one.
*
* Several templates in this module use or operate on eponymous templates that
Expand All
@@ -31,18 +31,19 @@
module std.meta ;
/**
* Creates a tuple out of a sequence of zero or more template arguments.
* Creates a sequence of zero or more aliases. This is most commonly
* used as template parameters or arguments.
*/
template Arguments (TList... )
template AliasSeq (TList... )
{
alias Arguments = TList;
alias AliasSeq = TList;
}
// /
unittest
{
import std.typetuple ;
alias TL = Arguments ! (int , double );
import std.meta ;
alias TL = AliasSeq ! (int , double );
int foo (TL td) // same as int foo(int, double);
{
Expand All
@@ -53,17 +54,12 @@ unittest
// /
unittest
{
alias TL = Arguments ! (int , double );
alias TL = AliasSeq ! (int , double );
alias Types = Arguments ! (TL , char );
static assert (is (Types == Arguments ! (int , double , char )));
alias Types = AliasSeq ! (TL , char );
static assert (is (Types == AliasSeq ! (int , double , char )));
}
/**
* Alternate name for $(LREF Arguments) for legacy compatibility.
*/
alias TypeTuple = Arguments;
/**
* Returns the index of the first occurrence of type T in the
* sequence of zero or more types TList.
Expand All
@@ -88,7 +84,7 @@ unittest
void foo ()
{
writefln(" The index of long is %s" ,
staticIndexOf! (long , TypeTuple ! (int , long , double )));
staticIndexOf! (long , AliasSeq ! (int , long , double )));
// prints: The index of long is 1
}
}
Expand Down
Expand Up
@@ -164,9 +160,9 @@ template Erase(alias T, TList...)
// /
unittest
{
alias Types = TypeTuple ! (int , long , double , char );
alias Types = AliasSeq ! (int , long , double , char );
alias TL = Erase! (long , Types);
static assert (is (TL == TypeTuple ! (int , double , char )));
static assert (is (TL == AliasSeq ! (int , double , char )));
}
// [internal]
Expand All
@@ -184,11 +180,11 @@ private template GenericErase(args...)
static if (isSame! (e, head))
alias result = tail;
else
alias result = TypeTuple ! (head, GenericErase! (e, tail).result);
alias result = AliasSeq ! (head, GenericErase! (e, tail).result);
}
else
{
alias result = TypeTuple ! ();
alias result = AliasSeq ! ();
}
}
Expand Down
Expand Up
@@ -222,10 +218,10 @@ template EraseAll(alias T, TList...)
// /
unittest
{
alias Types = TypeTuple ! (int , long , long , int );
alias Types = AliasSeq ! (int , long , long , int );
alias TL = EraseAll! (long , Types);
static assert (is (TL == TypeTuple ! (int , int )));
static assert (is (TL == AliasSeq ! (int , int )));
}
// [internal]
Expand All
@@ -244,11 +240,11 @@ private template GenericEraseAll(args...)
static if (isSame! (e, head))
alias result = next;
else
alias result = TypeTuple ! (head, next);
alias result = AliasSeq ! (head, next);
}
else
{
alias result = TypeTuple ! ();
alias result = AliasSeq ! ();
}
}
Expand All
@@ -274,16 +270,16 @@ template NoDuplicates(TList...)
alias NoDuplicates = TList;
else
alias NoDuplicates =
TypeTuple ! (TList[0 ], NoDuplicates! (EraseAll! (TList[0 ], TList[1 .. $])));
AliasSeq ! (TList[0 ], NoDuplicates! (EraseAll! (TList[0 ], TList[1 .. $])));
}
// /
unittest
{
alias Types = TypeTuple ! (int , long , long , int , float );
alias Types = AliasSeq ! (int , long , long , int , float );
alias TL = NoDuplicates! (Types);
static assert (is (TL == TypeTuple ! (int , long , float )));
static assert (is (TL == AliasSeq ! (int , long , float )));
}
unittest
Expand Down
Expand Up
@@ -325,10 +321,10 @@ template Replace(alias T, alias U, TList...)
// /
unittest
{
alias Types = TypeTuple ! (int , long , long , int , float );
alias Types = AliasSeq ! (int , long , long , int , float );
alias TL = Replace! (long , char , Types);
static assert (is (TL == TypeTuple ! (int , char , long , int , float )));
static assert (is (TL == AliasSeq ! (int , char , long , int , float )));
}
// [internal]
Expand All
@@ -345,14 +341,14 @@ private template GenericReplace(args...)
alias tail = tuple[1 .. $];
static if (isSame! (from, head))
alias result = TypeTuple ! (to, tail);
alias result = AliasSeq ! (to, tail);
else
alias result = TypeTuple ! (head,
alias result = AliasSeq ! (head,
GenericReplace! (from, to, tail).result);
}
else
{
alias result = TypeTuple ! ();
alias result = AliasSeq ! ();
}
}
Expand Down
Expand Up
@@ -405,10 +401,10 @@ template ReplaceAll(alias T, alias U, TList...)
// /
unittest
{
alias Types = TypeTuple ! (int , long , long , int , float );
alias Types = AliasSeq ! (int , long , long , int , float );
alias TL = ReplaceAll! (long , char , Types);
static assert (is (TL == TypeTuple ! (int , char , char , int , float )));
static assert (is (TL == AliasSeq ! (int , char , char , int , float )));
}
// [internal]
Expand All
@@ -426,13 +422,13 @@ private template GenericReplaceAll(args...)
alias next = GenericReplaceAll! (from, to, tail).result;
static if (isSame! (from, head))
alias result = TypeTuple ! (to, next);
alias result = AliasSeq ! (to, next);
else
alias result = TypeTuple ! (head, next);
alias result = AliasSeq ! (head, next);
}
else
{
alias result = TypeTuple ! ();
alias result = AliasSeq ! ();
}
}
Expand Down
Expand Up
@@ -467,7 +463,7 @@ template Reverse(TList...)
else
{
alias Reverse =
TypeTuple ! (
AliasSeq ! (
Reverse! (TList[$/ 2 .. $ ]),
Reverse! (TList[ 0 .. $/ 2 ]));
}
Expand All
@@ -476,10 +472,10 @@ template Reverse(TList...)
// /
unittest
{
alias Types = TypeTuple ! (int , long , long , int , float );
alias Types = AliasSeq ! (int , long , long , int , float );
alias TL = Reverse! (Types);
static assert (is (TL == TypeTuple ! (float , int , long , long , int )));
static assert (is (TL == AliasSeq ! (float , int , long , long , int )));
}
/**
Expand All
@@ -502,7 +498,7 @@ unittest
class A { }
class B : A { }
class C : B { }
alias Types = TypeTuple ! (A, C, B);
alias Types = AliasSeq ! (A, C, B);
MostDerived! (Object , Types) x; // x is declared as type C
static assert (is (typeof (x) == C));
Expand All
@@ -518,7 +514,7 @@ template DerivedToFront(TList...)
alias DerivedToFront = TList;
else
alias DerivedToFront =
TypeTuple ! (MostDerived! (TList[0 ], TList[1 .. $]),
AliasSeq ! (MostDerived! (TList[0 ], TList[1 .. $]),
DerivedToFront! (ReplaceAll! (MostDerived! (TList[0 ], TList[1 .. $]),
TList[0 ],
TList[1 .. $])));
Expand All
@@ -530,29 +526,29 @@ unittest
class A { }
class B : A { }
class C : B { }
alias Types = TypeTuple ! (A, C, B);
alias Types = AliasSeq ! (A, C, B);
alias TL = DerivedToFront! (Types);
static assert (is (TL == TypeTuple ! (C, B, A)));
static assert (is (TL == AliasSeq ! (C, B, A)));
}
/**
Evaluates to $(D TypeTuple !(F!(T[0]), F!(T[1]), ..., F!(T[$ - 1]))).
Evaluates to $(D AliasSeq !(F!(T[0]), F!(T[1]), ..., F!(T[$ - 1]))).
*/
template staticMap (alias F, T... )
{
static if (T.length == 0 )
{
alias staticMap = TypeTuple ! ();
alias staticMap = AliasSeq ! ();
}
else static if (T.length == 1 )
{
alias staticMap = TypeTuple ! (F! (T[0 ]));
alias staticMap = AliasSeq ! (F! (T[0 ]));
}
else
{
alias staticMap =
TypeTuple ! (
AliasSeq ! (
staticMap! (F, T[ 0 .. $/ 2 ]),
staticMap! (F, T[$/ 2 .. $ ]));
}
Expand All
@@ -563,7 +559,7 @@ unittest
{
import std.traits : Unqual;
alias TL = staticMap! (Unqual, int , const int , immutable int );
static assert (is (TL == TypeTuple ! (int , int , int )));
static assert (is (TL == AliasSeq ! (int , int , int )));
}
unittest
Expand All
@@ -576,10 +572,10 @@ unittest
// single
alias Single = staticMap! (Unqual, const int );
static assert (is (Single == TypeTuple ! int ));
static assert (is (Single == AliasSeq ! int ));
alias T = staticMap! (Unqual, int , const int , immutable int );
static assert (is (T == TypeTuple ! (int , int , int )));
static assert (is (T == AliasSeq ! (int , int , int )));
}
/**
Expand Down
Expand Up
@@ -652,26 +648,26 @@ unittest
/**
* Filters a $(D TypeTuple ) using a template predicate. Returns a
* $(D TypeTuple ) of the elements which satisfy the predicate.
* Filters an $(D AliasSeq ) using a template predicate. Returns a
* $(D AliasSeq ) of the elements which satisfy the predicate.
*/
template Filter (alias pred, TList... )
{
static if (TList.length == 0 )
{
alias Filter = TypeTuple ! ();
alias Filter = AliasSeq ! ();
}
else static if (TList.length == 1 )
{
static if (pred! (TList[0 ]))
alias Filter = TypeTuple ! (TList[0 ]);
alias Filter = AliasSeq ! (TList[0 ]);
else
alias Filter = TypeTuple ! ();
alias Filter = AliasSeq ! ();
}
else
{
alias Filter =
TypeTuple ! (
AliasSeq ! (
Filter! (pred, TList[ 0 .. $/ 2 ]),
Filter! (pred, TList[$/ 2 .. $ ]));
}
Expand All
@@ -682,21 +678,21 @@ unittest
{
import std.traits : isNarrowString, isUnsigned;
alias Types1 = TypeTuple ! (string , wstring , dchar [], char [], dstring , int );
alias Types1 = AliasSeq ! (string , wstring , dchar [], char [], dstring , int );
alias TL1 = Filter! (isNarrowString, Types1);
static assert (is (TL1 == TypeTuple ! (string , wstring , char [])));
static assert (is (TL1 == AliasSeq ! (string , wstring , char [])));
alias Types2 = TypeTuple ! (int , byte , ubyte , dstring , dchar , uint , ulong );
alias Types2 = AliasSeq ! (int , byte , ubyte , dstring , dchar , uint , ulong );
alias TL2 = Filter! (isUnsigned, Types2);
static assert (is (TL2 == TypeTuple ! (ubyte , uint , ulong )));
static assert (is (TL2 == AliasSeq ! (ubyte , uint , ulong )));
}
unittest
{
import std.traits : isPointer;
static assert (is (Filter! (isPointer, int , void * , char [], int * ) == TypeTuple ! (void * , int * )));
static assert (is (Filter! isPointer == TypeTuple ! ()));
static assert (is (Filter! (isPointer, int , void * , char [], int * ) == AliasSeq ! (void * , int * )));
static assert (is (Filter! isPointer == AliasSeq ! ()));
}
Expand Down
Expand Up
@@ -740,7 +736,7 @@ unittest
unittest
{
foreach (T; TypeTuple ! (int , staticMap, 42 ))
foreach (T; AliasSeq ! (int , staticMap, 42 ))
{
static assert (! Instantiate! (templateNot! testAlways, T));
static assert (Instantiate! (templateNot! testNever, T));
Expand Down
Expand Up
@@ -791,7 +787,7 @@ unittest
unittest
{
foreach (T; TypeTuple ! (int , staticMap, 42 ))
foreach (T; AliasSeq ! (int , staticMap, 42 ))
{
static assert ( Instantiate! (templateAnd! (), T));
static assert ( Instantiate! (templateAnd! (testAlways), T));
Expand Down
Expand Up
@@ -849,7 +845,7 @@ unittest
unittest
{
foreach (T; TypeTuple ! (int , staticMap, 42 ))
foreach (T; AliasSeq ! (int , staticMap, 42 ))
{
static assert ( Instantiate! (templateOr! (testAlways), T));
static assert ( Instantiate! (templateOr! (testAlways, testAlways), T));
Expand Down
Expand Up
@@ -1022,7 +1018,7 @@ unittest
* Instantiates the given template with the given list of parameters.
*
* Used to work around syntactic limitations of D with regard to instantiating
* a template from a type tuple (e.g. T[0]!(...) is not valid) or a template
* a template from an alias sequence (e.g. T[0]!(...) is not valid) or a template
* returning another template (e.g. Foo!(Bar)!(Baz) is not allowed).
*/
// TODO: Consider publicly exposing this, maybe even if only for better
Expand Down