c++templatesrecursiontypelist

How this recursive template works?


I am reading "C++ Templates - The complete guide" book and in the chapter of Typelists they mention some code that I can't fully understand while it expands to in their recursive call.

In using First = Front<List>; the code assigns the front type within the typelist. But in using Rest = typename LargestTypeT<PopFront<List>>::Type; first removes the front type then enters the template recursively by passing the typelist without the front type.

After that, the line using Type = IfThenElse<(sizeof(First) >= sizeof(Rest)), First, Rest>; compares if the First is greater or equals to Rest which, in my understanding, is a Typelist<...>.

That part is what I do not fully understand. So, how can a type can be compared with a Typelist<...> containing one or more elements? Specifically, what Rest expands to in the comparation with First in that line?

template<typename... Elements>
class Typelist
{
};

template<typename List>
class LargestTypeT;
// recursive case:
template<typename List>
class LargestTypeT
{
private:
using First = Front<List>;
using Rest = typename LargestTypeT<PopFront<List>>::Type; // This must expand as Typelist<...>
public:
//
// -> Doesn't know in what the below expands to.
// -> The `Rest` is currently expanded as `Typelist<...>` but how can be
// -> compared with the current type `First`?
using Type = IfThenElse<(sizeof(First) >= sizeof(Rest)), First, Rest>;
};
// basis case:
template<>
class LargestTypeT<Typelist<>>
{
public:
using Type = char; // This type is as comparation against
// the others just as the smallest type
};
template<typename List>
using LargestType = typename LargestTypeT<List>::Type;

Given the following typelist:

Typelist<bool, int, long, short>

LargestType will return the first, largest type within the typelist. Which can be int or long.

Here is the code for getting the first type in the list and also for removing the first element from the list. I have no problems understanding everything of the code below.

template<typename List>
class FrontT;
template<typename Head, typename... Tail>
class FrontT<Typelist<Head, Tail...>>
{
public:
using Type = Head;
};
template<typename List>
using Front = typename FrontT<List>::Type;

template<typename List>
class PopFrontT;
template<typename Head, typename... Tail>
class PopFrontT<Typelist<Head, Tail...>> {
public:
using Type = Typelist<Tail...>;
};
template<typename List>
using PopFront = typename PopFrontT<List>::Type;

Solution

  • Your mistake is thinking that Rest is a typelist, it is not. It is the result of LargestTypeT applied to a typelist.

    PopFront<List> is the typelist, and LargestTypeT finds the largest type in that. Rest is a confusing name, as it implies it is still a list, but it isn't.