How to create the Cartesian product of a type list?

前端 未结 9 1430
夕颜
夕颜 2020-11-28 09:15

I\'d like to create the cross product of a list of types using variadic templates.

Here\'s what I have so far:

#include 
#include <         


        
9条回答
  •  無奈伤痛
    2020-11-28 10:04

    So far all solutions have drawbacks, unnecessary dependencies, unnecessary helpers and all are restricted to the Cartesian power of two. The following solution has no such drawbacks and supports:

    1. Any cartesian power including 0.
    2. Returning the empty set if any of the factors is an empty set.
    3. The code is self contained and does not depend on any include files.
    4. The inputs of the function can be of any template type.
    5. The type of the output list can be specified via the first template parameter.

    It was actually to harder to implement (but good as homework) then I thought. I am actually thinking about creating a little generator which allows me an extended template syntax which makes these things really easy.

    Simplified the code works as follows: product converts an input list tuple,tuple,tuple into tuple...>, tuple, tuple. This second list is then passed to product_helper which does the recursive Cartesian product computation.

    template  struct cat2;
    
    template  class R, typename... As, typename... Bs>
    struct cat2 , R > {
            using type = R ;
    };
    
    template  struct product_helper;
    
    template  class R, typename... Ts>
    struct product_helper < R > { // stop condition
            using type = R< Ts...>;
    };
    
    template  class R, typename... Ts>
    struct product_helper < R >, Ts... > { // catches first empty tuple
            using type = R<>;
    };
    
    template  class R, typename... Ts, typename... Rests>
    struct product_helper < R, R<>, Rests... > { // catches any empty tuple except first
            using type = R<>;
    };
    
    template  class R, typename... X, typename H, typename... Rests>
    struct product_helper < R, R, Rests... > {
            using type1 = R  >::type...>;
            using type  = typename product_helper::type;
    };
    
    template  class R, typename... X, template class Head, typename T, typename... Ts, typename... Rests>
    struct product_helper < R, Head, Rests... > {
            using type1 = R  >::type...>;
            using type2 = typename product_helper , R >::type;
            using type3 = typename cat2::type;
            using type  = typename product_helper::type;
    };
    
    template  class R, typename... Ts> struct product;
    
    template  class R>
    struct product < R > { // no input, R specifies the return type
        using type = R<>;
    };
    
    template  class R, template class Head, typename... Ts, typename... Tail>
    struct product , Tail... > { // R is the return type, Head is the first input list
        using type = typename product_helper< R...>, Tail... >::type;
    };
    

    Here is a compilable example of how the code can be used.

提交回复
热议问题