phobos/std/typetuple.d
Andrei Alexandrescu bcfdd75970 minor
2009-04-06 18:32:37 +00:00

260 lines
6 KiB
D

// Written in the D programming language.
/**
* Templates with which to manipulate type tuples (also known as type lists).
*
* Some operations on type tuples 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
* list that is a slice of the old one.
*
* References:
* Based on ideas in Table 3.1 from
* $(LINK2 http://www.amazon.com/exec/obidos/ASIN/0201704315/ref=ase_classicempire/102-2957199-2585768,
* Modern C++ Design),
* Andrei Alexandrescu (Addison-Wesley Professional, 2001)
* Macros:
* WIKI = Phobos/StdTypeTuple
* Copyright:
* Public Domain
*/
/* Author:
* Walter Bright, Digital Mars, www.digitalmars.com
*/
module std.typetuple;
/**
* Creates a typetuple out of a sequence of zero or more types.
* Example:
* ---
* import std.typetuple;
* alias TypeTuple!(int, double) TL;
*
* int foo(TL td) // same as int foo(int, double);
* {
* return td[0] + cast(int)td[1];
* }
* ---
*
* Example:
* ---
* TypeTuple!(TL, char)
* // is equivalent to:
* TypeTuple!(int, double, char)
* ---
*/
template TypeTuple(TList...)
{
alias TList TypeTuple;
}
/**
* Returns the index of the first occurrence of type T in the
* sequence of zero or more types TList.
* If not found, -1 is returned.
* Example:
* ---
* import std.typetuple;
* import std.stdio;
*
* void foo()
* {
* writefln("The index of long is ",
* indexOf!(long, TypeTuple!(int, long, double)));
* // prints: The index of long is 1
* }
* ---
*/
template indexOf(T, TList...)
{
static if (TList.length == 0)
enum int indexOf = -1;
else static if (is(T == TList[0]))
enum int indexOf = 0;
else
enum int indexOf =
(indexOf!(T, TList[1 .. length]) == -1)
? -1
: 1 + indexOf!(T, TList[1 .. length]);
}
/// Kept for backwards compatibility
alias indexOf IndexOf;
/**
* Returns a typetuple created from TList with the first occurrence,
* if any, of T removed.
* Example:
* ---
* Erase!(long, int, long, double, char)
* // is the same as:
* TypeTuple!(int, double, char)
* ---
*/
template Erase(T, TList...)
{
static if (TList.length == 0)
alias TList Erase;
else static if (is(T == TList[0]))
alias TList[1 .. length] Erase;
else
alias TypeTuple!(TList[0], Erase!(T, TList[1 .. length])) Erase;
}
/**
* Returns a typetuple created from TList with the all occurrences,
* if any, of T removed.
* Example:
* ---
* alias TypeTuple!(int, long, long, int) TL;
*
* EraseAll!(long, TL)
* // is the same as:
* TypeTuple!(int, int)
* ---
*/
template EraseAll(T, TList...)
{
static if (TList.length == 0)
alias TList EraseAll;
else static if (is(T == TList[0]))
alias EraseAll!(T, TList[1 .. length]) EraseAll;
else
alias TypeTuple!(TList[0], EraseAll!(T, TList[1 .. length])) EraseAll;
}
/**
* Returns a typetuple created from TList with the all duplicate
* types removed.
* Example:
* ---
* alias TypeTuple!(int, long, long, int, float) TL;
*
* NoDuplicates!(TL)
* // is the same as:
* TypeTuple!(int, long, float)
* ---
*/
template NoDuplicates(TList...)
{
static if (TList.length == 0)
alias TList NoDuplicates;
else
alias TypeTuple!(TList[0], NoDuplicates!(EraseAll!(TList[0], TList[1 .. length]))) NoDuplicates;
}
/**
* Returns a typetuple created from TList with the first occurrence
* of type T, if found, replaced with type U.
* Example:
* ---
* alias TypeTuple!(int, long, long, int, float) TL;
*
* Replace!(long, char, TL)
* // is the same as:
* TypeTuple!(int, char, long, int, float)
* ---
*/
template Replace(T, U, TList...)
{
static if (TList.length == 0)
alias TList Replace;
else static if (is(T == TList[0]))
alias TypeTuple!(U, TList[1 .. length]) Replace;
else
alias TypeTuple!(TList[0], Replace!(T, U, TList[1 .. length])) Replace;
}
/**
* Returns a typetuple created from TList with all occurrences
* of type T, if found, replaced with type U.
* Example:
* ---
* alias TypeTuple!(int, long, long, int, float) TL;
*
* ReplaceAll!(long, char, TL)
* // is the same as:
* TypeTuple!(int, char, char, int, float)
* ---
*/
template ReplaceAll(T, U, TList...)
{
static if (TList.length == 0)
alias TList ReplaceAll;
else static if (is(T == TList[0]))
alias TypeTuple!(U, ReplaceAll!(T, U, TList[1 .. length])) ReplaceAll;
else
alias TypeTuple!(TList[0], ReplaceAll!(T, U, TList[1 .. length])) ReplaceAll;
}
/**
* Returns a typetuple created from TList with the order reversed.
* Example:
* ---
* alias TypeTuple!(int, long, long, int, float) TL;
*
* Reverse!(TL)
* // is the same as:
* TypeTuple!(float, int, long, long, int)
* ---
*/
template Reverse(TList...)
{
static if (TList.length == 0)
alias TList Reverse;
else
alias TypeTuple!(Reverse!(TList[1 .. length]), TList[0]) Reverse;
}
/**
* Returns the type from TList that is the most derived from type T.
* If none are found, T is returned.
* Example:
* ---
* class A { }
* class B : A { }
* class C : B { }
* alias TypeTuple!(A, C, B) TL;
*
* MostDerived!(Object, TL) x; // x is declared as type C
* ---
*/
template MostDerived(T, TList...)
{
static if (TList.length == 0)
alias T MostDerived;
else static if (is(TList[0] : T))
alias MostDerived!(TList[0], TList[1 .. length]) MostDerived;
else
alias MostDerived!(T, TList[1 .. length]) MostDerived;
}
/**
* Returns the typetuple TList with the types sorted so that the most
* derived types come first.
* Example:
* ---
* class A { }
* class B : A { }
* class C : B { }
* alias TypeTuple!(A, C, B) TL;
*
* DerivedToFront!(TL)
* // is the same as:
* TypeTuple!(C, B, A)
* ---
*/
template DerivedToFront(TList...)
{
static if (TList.length == 0)
alias TList DerivedToFront;
else
alias TypeTuple!(MostDerived!(TList[0], TList[1 .. length]),
DerivedToFront!(ReplaceAll!(MostDerived!(TList[0], TList[1 .. length]),
TList[0],
TList[1 .. length]))) DerivedToFront;
}