可以在以后解压缩类型元组吗?

时间:2012-06-02 09:05:10

标签: c++ c++11 variadic-templates

我有一个编码为

的类型元组
template<class... T>struct packed;

我想稍后将其解压缩,如

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

所以,我可以将它用作

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

注意,我不想像

那样立即解包元组的元素
template<class... T>
struct unpack<packed<T...>> : T...{};
template<class Packed>
struct foo: unpack<Packed>{};

我感兴趣的是将元组'packed'的元素作为'foo'的直接基类而不是通过'unack'的间接基类。元组类型的元素也是不同的非原始类型和非最终类型。

为了使示例更加详细,

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

我感兴趣的是foo应该直接来自node s

3 个答案:

答案 0 :(得分:2)

你可以这样做:

template <class>
struct foo;

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

然后您可以将其用作:

typedef packed<A, B, C> packed_type;
typedef foo<packed_type> foo_t;  // foo_t derives from A, B, and C

答案 1 :(得分:1)

N.B。这部分问题是不可能的:

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

Packed不是此处的参数包,因此无法在包扩展中使用。 如果您将其更改为:

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

然后你可以扩展参数包,但现在unpack只会传递一个类型,并且无法知道它是哪个索引,即N应该是node<Pn, N> 1}}

要使其工作,您需要将类型参数包与您的values接近的非整数参数包组合在一起,但是您具有从unpack派生的间接性node类型列表。

我认为这是你要求的(在误解node部分后编辑),使用我的index_tuple实用程序,可以很容易地被litb的seq模板替换相似的类型。非整数类型的参数包被推导为默认模板参数,然后可以在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;
}

答案 2 :(得分:1)

第二次尝试......

专门化foo接受特殊标记类型是否可以接受,该类型传入类型和相应的索引?

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'

(未经考验,对不起,我得出去!)