CodePlexProject Hosting for Open Source Software

Below you can see other examples of meta-functions which manipulate typelists. The first will "return" a type at position POS in the list:

The first line defines the "interface", as in out first example (and as in all following ones). The main recursive work is defined by the first specialized definition:

It takes the*rest* of thelist, and tries to find an element at position POS-1. In this example you can also note the 2nd way to "return values" from the meta-functions: returning a type using
*typedef* (until now we used *enum* to return numeric values). We also had to use
*typename* keyword (we've seen it in the previous sections too).

Next we define a specialized version to terminate the recursion - once POS reached 0, we want to return current type:

The last version is used for out-of-bound condition: if someone requested an element in 6-th position from the list with 5 elements, compile-time error will be produced:

It takes some time to get used to the syntax and to be able to read such constructs easily (if you can ever do this...), this is the reason I preferred to demonstrate those concept in*scheme* programs first, as their code is much more intuitive.

Following 2 examples look very similar to the first one above, so additional explanations won't help much, you just need to read it by yourself.

And a code to demonstrate those meta-functions "in action":

/** * Extraction of a type at specific position */ template <typename TLIST, int POS> struct tlist_get_type; template <typename HEAD, typename TAIL, int POS> struct tlist_get_type< typelist<HEAD, TAIL>, POS > { typedef typename tlist_get_type<TAIL, POS-1>::type type; }; template <typename T, typename TAIL> struct tlist_get_type< typelist<T, TAIL>, 0 > { typedef T type; }; template <int POS> struct tlist_get_type< nulltype, POS > { // no typedef - compilation error };

The first line defines the "interface", as in out first example (and as in all following ones). The main recursive work is defined by the first specialized definition:

template <typename HEAD, typename TAIL, int POS> struct tlist_get_type< typelist<HEAD, TAIL>, POS > { typedef typename tlist_get_type<TAIL, POS-1>::type type; };

It takes the

Next we define a specialized version to terminate the recursion - once POS reached 0, we want to return current type:

template <typename T, typename TAIL> struct tlist_get_type< typelist<T, TAIL>, 0 > { typedef T type; };

The last version is used for out-of-bound condition: if someone requested an element in 6-th position from the list with 5 elements, compile-time error will be produced:

template <int POS> struct tlist_get_type< nulltype, POS > { // no typedef - compilation error };

It takes some time to get used to the syntax and to be able to read such constructs easily (if you can ever do this...), this is the reason I preferred to demonstrate those concept in

Following 2 examples look very similar to the first one above, so additional explanations won't help much, you just need to read it by yourself.

/** * Find the largest type (in terms of "sizeof") */ template <typename TLIST> struct largest_type; template <typename HEAD, typename TAIL> struct largest_type< typelist<HEAD, TAIL> > { typedef typename largest_type<TAIL>::type _largest_tail; typedef typename type_if<sizeof(HEAD) >= sizeof(_largest_tail), HEAD, _largest_tail>::type type; }; template <typename T> struct largest_type< typelist<T, nulltype> > { typedef T type; }; /** * Find index of a type */ template <typename TLIST, typename T> struct index_of_type; template <typename HEAD, typename TAIL, typename T> struct index_of_type< typelist<HEAD, TAIL>, T> { enum { value = 1 + index_of_type<TAIL, T>::value }; }; template <typename T, typename TAIL> struct index_of_type< typelist<T, TAIL>, T > { enum { value = 0 }; }; template <typename NOTFOUND> struct index_of_type< nulltype, NOTFOUND > { // no value defined };

And a code to demonstrate those meta-functions "in action":

void test_typelists(void) { typedef TYPELIST_5(char, int, std::string, double, unsigned long) tlist; std::cout << "The sizes of 1st and 4th types are: " << sizeof(tlist_get_type<tlist, 0>::type) << ", " << sizeof(tlist_get_type<tlist, 3>::type) << std::endl; /*THIS LINE SHOULD NOT COMPILE*/ // typedef tlist_get_type<tlist, 5>::type overflow; std::cout << "The size of largest type is: " << sizeof(largest_type<tlist>::type) << std::endl; std::cout << "Index of \"std::string\" is: " << index_of_type<tlist, std::string>::value << ", " << "and of \"ulong\" is: " << index_of_type<tlist, unsigned long>::value << std::endl; /*THIS LINE SHOULD NOT COMPILE*/ //int notfound = index_of_type<tlist, float>::value; } // The output: //The sizes of 1st and 4th types are: 1, 8 //The size of largest type is: 32 //Index of "std::string" is: 2, and of "ulong" is: 4

Last edited Nov 30, 2007 at 6:44 AM by migo, version 1