Transform variadic template parameters to another types

后端 未结 2 511
清酒与你
清酒与你 2020-12-29 09:45

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

For example:

template 
struct single
{
   std::tuple&l         


        
相关标签:
2条回答
  • 2020-12-29 09:52

    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)>());
        }
    };
    
    0 讨论(0)
  • 2020-12-29 10:04

    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.
    0 讨论(0)
提交回复
热议问题