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;
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.