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

发布于 2024-10-21 00:51:57 字数 1155 浏览 7 评论 0 原文

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

例如:

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, std::vector>序列。并从中获得单身。

std::vector> 对我来说是个坏主意,因为我需要完整的一个序列,并且很容易从 .

是否可以?

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

How to transform types from variadic template parameters to another type?

For example:

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

I want to write so:

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

And have std::tuple<std::vector<int>, std::vector<double>, std::vector<double>> in struct sequences. And get single from it.

std::vector<single<T...>> is bad idea for me, because i need get one sequence full to and it's easy to copy it from .

Is it possible?

Thank you very much. Sorry for my bad English.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

热鲨 2024-10-28 00:51:58

好吧,这可能看起来有点矫枉过正,但是这样怎么样:据我所知,“迭代”变量的唯一选择是使用 表示法和针对简单 情况的模板专门化。

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

简单的情况:

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

递归的情况:

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

免责声明:未经测试,甚至没有编译,但我想你明白了基本的想法。至少还存在两个问题:

  1. get() 的返回值不是单个结构体,而是一个元组链。也许您可以使用 std::get<0> 递归地解开它...
  2. 我不知道 get_sequence_internal 的特化是否会生成编译时错误,因为 V 可以与 T 不同。

OK, this might seem a bit like overkill but how about this: As far as I know the only option to "iterate" variadics is using the <head, tail...> notation with a template specialization for the simple <head-only> case.

Therefore you could try something like this:

simple case:

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

recursive case:

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

Disclaimer: not tested, not even compiled, but I suppose you get the basic idea. At least two problems remain:

  1. The return value of get() is not your single struct but a tuple chain. Perhaps you can unchain it recursively with std::get<0>...
  2. I don't know if the specialization of get_sequence_internal generates a compile time error because the type of V can differ from T.
孤者何惧 2024-10-28 00:51:57

您不仅可以将可变参数包扩展为普通列表:您还可以扩展表达式。因此,您可以将 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)>());
    }
};

You can do more than just expand a variadic parameter pack as a plain list: you can expand an expression too. You can therefore have m_sequences be a tuple of vectors rather than a tuple of the elements:

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

You can also do nifty tricks with parameter packs to pick the appropriate element from the vector:

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)>());
    }
};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文