1

I have a tuple of types encoded as

template<class... T>struct packed;

I want to unpack it later like

template<class T>struct unpack;
template<class... T>
struct unpack<packed<T...>>{
      //how to define the unpacked type here?
};

So that, I can use it as

template<class Packed>
struct foo : unpack<Packed>::type...{};

Note, I do not want to unpack the elements of the tuple immediately like

template<class... T>
struct unpack<packed<T...>> : T...{};
template<class Packed>
struct foo: unpack<Packed>{};

I am interested to have elements of the tuple 'packed' to be direct base classes of 'foo' instead of indirect base classes via 'unack'. Also the elements of the type tuple are distinct non-primitive and non-final types.

To make the example more detailed,

template<class T, T... Values> 
struct variadic_values{};
template<class T,T From,class Encode,T To>
struct value_gen;
template<class T, T From, T... Values, T To>
struct value_gen<T,From,variadic_values<T,Values...>,To>
{
   using type = typename value_gen<T,From+1,variadic_values<T,Values...,From>,To>::type;
};
template<class T,T From,T... Values>
struct value_gen<T,From,variadic_values<T,Values...>,From>
{
    using type = variadic_values<T,Values...>;
};
template<class T, T From,T To>
using values = typename value_gen<T,From,variadic_values<T>,To>::type;
template<unsigned Idx,class T>
struct node{};
template<class Idx,class... Ts>
struct unpack;
template<unsigned... Idx,class...Ts>
struct unpack<variadic_values<unsigned,Idx...>,Ts...> : node<Idx,Ts>...{};
template<class... Ts>
class foo : unpack<values<unsigned,0,sizeof...(ts)>,Ts...>{};

What I am interested to have is that foo should be directly derived from nodes

abir
  • 1,797
  • 14
  • 26
  • It's not quite the same question, but I think some of the solutions to http://stackoverflow.com/questions/7858817/unpacking-a-tuple-to-call-a-matching-function-pointer would also work for this. – Flexo Jun 02 '12 at 09:17
  • I had gone though the solution before, but failed to convert it to a solution whet types are unpacked one by one rather than at a time. See comment on @HighCommander4 – abir Jun 02 '12 at 09:34

3 Answers3

2

You can do:

template <class>
struct foo;

template <class... T>
struct foo<packed<T...>> : T...
{
};

Then you can use it as:

typedef packed<A, B, C> packed_type;
typedef foo<packed_type> foo_t;  // foo_t derives from A, B, and C
HighCommander4
  • 50,428
  • 24
  • 122
  • 194
1

N.B. this part of your question is not possible:

template<class Packed>
struct foo : unpack<Packed>::type...{};

Packed is not a parameter pack here, so cannot be used in a pack expansion. If you changed it to:

template<class Packed>
struct foo<packed<Packed...> : unpack<Packed>::type...{};

then you could expand the parameter pack, but now unpack would only be passed a single type, and would have no way to know which index it was, i.e. what N should be for node<Pn, N>

To make it work you need to combine the type parameter pack with a non-type parameter pack of integers, which your values gets close to, but you have the indirection of deriving from unpack not a list of node types.

I think this is what you're asking for (edited after misunderstanding the node part), using my index_tuple utility, which could easily be replaced by litb's seq template or any similar type. The non-type parameter pack of integers is deduced as a default template argument and can then be used in the base-class list of foo:

#include <redi/index_tuple.h>

template<typename T, unsigned N> struct node { };

template<typename... T> struct packed { };

template<typename T>
struct index_tuple_from_packed;

template<typename... T>
struct index_tuple_from_packed<packed<T...>>
{
  typedef redi::to_index_tuple<T...> type;
};

template<typename T, typename I = typename index_tuple_from_packed<T>::type>
struct foo;

template<typename... T, unsigned... Indices>
struct foo<packed<T...>, redi::index_tuple<Indices...>>
: node<T, Indices>...
{ };

struct A { };
struct B { };
struct C { };

int main()
{
  typedef packed<A, B, C> p;
  foo<p> d;
  node<A, 0>* a = &d;
  node<B, 1>* b = &d;
  node<C, 2>* c = &d;
}
Community
  • 1
  • 1
Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521
  • I guess "index_tuple" or "seq" are nearly same as "values" and value_gen in my example. See later part of the example. You are using make_derived<...>::type as the implementation, while I am looking for make_derived to look like that (in my example it is foo).though I can use template alias for that but I want to have a class template instead of alias. – abir Jun 02 '12 at 11:28
  • I got rid of `make_derived`, please reload – Jonathan Wakely Jun 02 '12 at 11:29
  • This is very close to the solution, however as foo is to take variadic types, it is not possible to add default type at end. I agree some confusion about foo is in the question. Look at the last part, where templatefoo; is defined. – abir Jun 02 '12 at 11:49
  • Then I don't an easy solution, you need some way to get the integer list available in the base-clause of `foo`, so it has to be a template parameter. I _think_ you either have to change the template parameters of `foo` or accept an indirection instead of deriving directly from `node`. Hmm, just had another idea that won't fit in a comment ... – Jonathan Wakely Jun 02 '12 at 11:55
1

Second try ...

Would it be acceptable to specialize foo to accept a special tag type, which passes in the type and corresponding index?

template<typename T, unsigned N>
struct tagged_node
{ };

template<typename...>
struct foo;

// specialize for case where pack is list of special tag types.
template<typename... T, unsigned... N>
struct foo<tagged_node<T, N>...> : node<T,N>...
{ };

template<typename T, unsigned N>
struct wrapped_node
{ typedef node<T, N> type; };

template<typename T, typename U>
struct make_node_foo_impl;

template<typename... T, unsigned... I>
struct make_node_foo_impl<packed<T...>, index_tuple<I...>>
{
  typedef foo<tagged_node<T, I>...> type;
};   

template<typename... T>
struct make_node_foo
: make_node_foo_impl<packed<T...>, to_index_tuple<T...>>
{ };  // inherits 'type'

(Untested, sorry, I have to go out!)

Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521