I would like to know how can I do the following in C++:
Consider these classes :
C1 < C2 < C3 < ... < Cn,
Ci < Cj
means sizeof(Ci) < sizeof(Cj)
I want a structure that uses variadic templates as a sequence of Ci
's,
OrderBySize<AnySequenceOfCis>
, for example : OrderBySize<C1,C2,C3,...,Cn>
or
OrderBySize<C2,C1,C3,C4,...,Cn>
... all possible combinations
and gives the following structure as a result :
class result{
Cn elem1;
Cn-1 elem2;
.
.
.
C1 elemn;
}
I read this article, it shows how we can define a Tuple<typename ...T>
, however, this is different, much more difficult to implement and very useful.
EDIT :
order_by_size<T1, ..., Tn>
would contain a tuple of the ordered combination of T1, ..., Tn
However I don't want the user to know that I am ordering the fields, the user would use it like a tuple. And thus, in order to access the fields, the user will use :
template<typename... Tn>
get<size_t>(const MyStructure<Tn ...>& m)
to get the size_t
'th element which is has an other index in the new tuple
.
Basically this problem reduces to just sorting a list of types based on a given comparator. Once you have that, everything else follows. So this answer is just the sorting part. We'll start with a typelist:
I'm going to assume a bunch of metafunctions which are very short (
head
,tail
,concat
,size
). I will omit them for brevity.So let's just jump into writing merge sort:
The general structure here should look familiar. We split our typelist,
TL
, into two equal parts, sort both, and then merge. Of course, this is metaprogramming, so everything is unnecessarily complicated.Let's start with
split
.split
takes a typelist and a size, and returns a typelist of two typelists: the first having the given size, and the second being the remainder:So that gives us
left
andright
(at least once we applyhead_t<>
andhead_t<tail_t<>>
). All that's left is themerge
step. I'm using the Boost MPL idea of what a metafunction class is, soLessSize
is:merge
just has to walk both typelists and pick the smallest element based on the comparator between the two typelists. First, we'll start with all of our base cases:And then the recursive step, which is somewhat ugly:
Basically, given two typelists,
{A, As...}
and{B, Bs...}
, we select the smallest based onCmp
, and that's the side we're popping the element off of. IfCmp::apply<A,B>
, then we're concatenatingA
with the result of merging{As...}
with{B, Bs...}
. And vice versa.And that's all she wrote:
Once you have the sorted types, making a tuple is straightforward:
Now just add overloads for
get<>
onmy_tuple<T...>
: