将可变参数模板参数转换为其他类型

时间:2011-03-08 16:23:34

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

如何将类型从可变参数模板参数转换为另一种类型?

例如:

template <typename... T>
struct single
{
   std::tuple<T...> m_single;
};

template <typename... T>
struct sequences
{
   single<T...> get(size_t pos)
   {
       // I don't know how to convert here
       return std::make_tuple(std::get<0>(m_sequences)[pos]... std::get<N>(m_sequences)[pos]);
   }

   template <size_t Idx>
   std::vector<
      typename std::tuple_element<Idx, std::tuple<T...>>::type
      >
   get_sequence()
   {
      return std::get<Idx>(m_sequences);
   }

   std::tuple<T...> m_sequences; // std::tuple<std::vector<T...>> I don't know how to conver here
};

我想这样写:

sequences<int, double, double> seq;
single<int, double, double> sin = seq.get(10);

在结构序列中有std::tuple<std::vector<int>, std::vector<double>, std::vector<double>>。并从中获得单身。

std::vector<single<T...>>对我来说不是一个好主意,因为我需要一个完整的序列,并且很容易从中复制它。

有可能吗?

非常感谢你。抱歉我的英语不好。

2 个答案:

答案 0 :(得分:15)

您可以做的不仅仅是将可变参数包扩展为普通列表:您也可以扩展表达式。因此,您可以m_sequences为向量元组而不是元素元组:

template <typename... T>
struct sequences
{
   std::tuple<std::vector<T>...> m_sequences;
};

你也可以使用参数包做一些漂亮的技巧,从矢量中选择适当的元素:

template<size_t ... Indices> struct indices_holder
{};

template<size_t index_to_add,typename Indices=indices_holder<> >
struct make_indices_impl;

template<size_t index_to_add,size_t...existing_indices>
struct make_indices_impl<index_to_add,indices_holder<existing_indices...> >
{
    typedef typename make_indices_impl<
        index_to_add-1,
        indices_holder<index_to_add-1,existing_indices...> >::type type;
};

template<size_t... existing_indices>
struct make_indices_impl<0,indices_holder<existing_indices...> >
{
    typedef indices_holder<existing_indices...>  type;
};

template<size_t max_index>
typename make_indices_impl<max_index>::type make_indices()
{
    return typename make_indices_impl<max_index>::type();
}



template <typename... T>
struct sequences
{
    std::tuple<std::vector<T>...> m_sequences;

    template<size_t... Indices>
    std::tuple<T...> get_impl(size_t pos,indices_holder<Indices...>)
    {
        return std::make_tuple(std::get<Indices>(m_sequences)[pos]...);
    }

    std::tuple<T...> get(size_t pos)
    {
        return get_impl(pos,make_indices<sizeof...(T)>());
    }
};

答案 1 :(得分:2)

好吧,这看起来有点像矫枉过正但是如何:据我所知,“迭代”可变参数的唯一选择是使用<head, tail...>表示法和简单{{1}的模板专门化} case。

因此你可以尝试这样的事情:

简单案例:

<head-only>

递归案例:

template <typename T>
struct sequences
{
   std::tuple<T> get(size_t pos)
   {
     return values[pos];
   }

   std::vector<T> get_sequence()
   {
      return values;
   }

   std::vector<T> values;
};

免责声明:未经测试,甚至未编译,但我认为您已获得基本想法。至少还有两个问题:

  1. template <typename T, typename ...U> struct sequences { std::tuple<T, std::tuple<U...> > get(size_t pos) { return std::make_tuple(values[pos], remainder->get(pos)); } template <size_t Idx> std::vector< typename std::tuple_element<Idx, std::tuple<T...>>::type > get_sequence() { return get_sequence_internal< typename std::tuple_element<Idx, std::tuple<T...>>::type, Idx >(); } template <typename V, 0> std::vector<V> get_sequence_internal() { return values; } template <typename V, size_t Idx> std::vector<V> get_sequence() { return remainder->getSequence_internal<V, Idx-1>(); } std::vector<T> values; sequences<U...>* remainder; }; 的返回值不是您的单个结构,而是一个元组链。也许你可以用get() ...
  2. 递归地解除它
  3. 我不知道get_sequence_internal的特化是否会产生编译时错误,因为std::get<0>的类型可能与V不同。