Home > database >  Cascade variadic template template parameters
Cascade variadic template template parameters

Time:07-13

How can I cascade variadic types? I.e.:

template <typename... T>
using Cascade = ???; // T1<T2<T3<...>>>

Example:

using Vector2D = Cascade<std::vector, std::vector, double>;
static_assert(std::is_same_v<Vector2D, std::vector<std::vector<double>>>);

CodePudding user response:

You cannot have CascadeRight. T1 is not a typename, it is a template, and so are most of the others, but the last one is a typename. You cannot have different parameter kinds (both types and templates) in the same parameter pack. You also cannot have anything after a parameter pack.

You can have CascadeLeft like this:

  template <typename K, template <typename...> class ... T>
  class CascadeLeft;                  
                                      
  template <typename K>               
  class CascadeLeft<K>                
  {                                   
      using type = K;                 
  };                                  
                                      
  template <typename K, 
            template <typename...> class T0, 
            template <typename...> class... T>
  class CascadeLeft<K, T0, T...>      
  {                                   
      using type = typename CascadeLeft<T0<K>, T...>::type;
  };   

Frankly, std::vector<std::vector<double>> is much more transparent than CascadeLeft<double, std::vector, std::vector>, so I wouldn't bother.

CodePudding user response:

Expanding on the accepted answer with CascadeRight and support for multiple types for the innermost template:

template<template<typename...> typename Head, template<typename...> typename... Tail>
struct CascadeRight {
    template<typename... T>
    using type = Head<typename CascadeRight<Tail...>::type<T...>>;
};

template<template<typename...> typename Head>
struct CascadeRight<Head> {
    template<typename... T>
    using type = Head<T...>;
};

template<template<typename...> typename Head, template<typename...> typename... Tail>
struct CascadeLeft {
    template<typename... T>
    using type = typename CascadeLeft<Tail...>::type<Head<T...>>;
};

template<template<typename...> typename Head>
struct CascadeLeft<Head> {
    template<typename... T>
    using type = Head<T...>;
};
using T1 = CascadeRight<std::vector, std::map>::type<int, double>;
using T2 = CascadeLeft<std::map, std::vector>::type<int, double>;
  • Related