3.9 Erasing a Type from a Typelist
Now for the opposite operation— erasing a type from a typelist—we have two options: Erase only the first occurrence, or erase all occurrences of a given type.
Let's think of removing only the first occurrence.
Erase Input: Typelist TList, type T Output: Inner type definition Result
If TList is NullType, then Result is NullType. Else If T is the same as TList::Head, then Result is TList::Tail. Else Result is a typelist having TList::Head as its head and the result of applying Erase to TList::Tail and T as its tail.
Here's how this algorithm maps to C++.
template <class TList, class T> struct Erase;
template <class T> // Specialization 1
struct Erase<NullType, T>
{
typedef NullType Result;
};
template <class T, class Tail> // Specialization 2
struct Erase<Typelist<T, Tail>, T>
{
typedef Tail Result;
};
template <class Head, class Tail, class T> // Specialization 3
struct Erase<Typelist<Head, Tail>, T>
{
typedef Typelist<Head,
typename Erase<Tail, T>::Result>
Result;
};
As in the case of TypeAt, there is no default version of the template. This means you can instantiate Erase only with certain types. For instance, Erase<double, int> yields a compile-time error because there's no match for it. Erase needs its first parameter to be a typelist.
Using our SignedTypes definition, we can now say the following:
// SomeSignedTypes contains the equivalent of
// TYPELIST_6(signed char, short int, int, long int,
// double, long double)
typedef Erase<SignedTypes, float>::Result SomeSignedTypes;
Let's tap into the recursive erase algorithm. The EraseAll template erases all occurrences of a type in a typelist. The implementation is similar to Erase's, with one difference. When detecting a type to erase, the algorithm doesn't stop. EraseAll continues looking for and removing matches down the tail of the list by recursively applying itself:
template <class TList, class T> struct EraseAll;
template <class T>
struct EraseAll<NullType, T>
{
typedef NullType Result;
};
template <class T, class Tail>
struct EraseAll<Typelist<T, Tail>, T>
{
// Go all the way down the list removing the type
typedef typename EraseAll<Tail, T>::Result Result;
};
template <class Head, class Tail, class T>
struct EraseAll<Typelist<Head, Tail>, T>
{
// Go all the way down the list removing the type
typedef Typelist<Head,
typename EraseAll<Tail, T>::Result>
Result;
};
|