alpaka
Abstraction Library for Parallel Kernel Acceleration
CartesianProduct.hpp
Go to the documentation of this file.
1 /* Copyright 2022 Benjamin Worpitz, Bernhard Manfred Gruber
2  * SPDX-License-Identifier: MPL-2.0
3  */
4 
5 #pragma once
6 
8 
9 namespace alpaka::meta
10 {
11  // This is based on code by Patrick Fromberg.
12  // See
13  // http://stackoverflow.com/questions/9122028/how-to-create-the-cartesian-product-of-a-type-list/19611856#19611856
14  namespace detail
15  {
16  template<typename... Ts>
18 
19  // Stop condition.
20  template<template<typename...> class TList, typename... Ts>
21  struct CartesianProductImplHelper<TList<Ts...>>
22  {
23  using type = TList<Ts...>;
24  };
25 
26  // Catches first empty tuple.
27  template<template<typename...> class TList, typename... Ts>
28  struct CartesianProductImplHelper<TList<TList<>>, Ts...>
29  {
30  using type = TList<>;
31  };
32 
33  // Catches any empty tuple except first.
34  template<template<typename...> class TList, typename... Ts, typename... Rests>
35  struct CartesianProductImplHelper<TList<Ts...>, TList<>, Rests...>
36  {
37  using type = TList<>;
38  };
39 
40  template<template<typename...> class TList, typename... X, typename H, typename... Rests>
41  struct CartesianProductImplHelper<TList<X...>, TList<H>, Rests...>
42  {
43  using type1 = TList<Concatenate<X, TList<H>>...>;
44  using type = typename CartesianProductImplHelper<type1, Rests...>::type;
45  };
46 
47  template<
48  template<typename...>
49  class TList,
50  typename... X,
51  template<typename...>
52  class Head,
53  typename T,
54  typename... Ts,
55  typename... Rests>
56  struct CartesianProductImplHelper<TList<X...>, Head<T, Ts...>, Rests...>
57  {
58  using type1 = TList<Concatenate<X, TList<T>>...>;
59  using type2 = typename CartesianProductImplHelper<TList<X...>, TList<Ts...>>::type;
61  using type = typename CartesianProductImplHelper<type3, Rests...>::type;
62  };
63 
64  template<template<typename...> class TList, typename... Ts>
66 
67  // The base case for no input returns an empty sequence.
68  template<template<typename...> class TList>
69  struct CartesianProductImpl<TList>
70  {
71  using type = TList<>;
72  };
73 
74  // R is the return type, Head<A...> is the first input list
75  template<template<typename...> class TList, template<typename...> class Head, typename... Ts, typename... Tail>
76  struct CartesianProductImpl<TList, Head<Ts...>, Tail...>
77  {
79  };
80  } // namespace detail
81 
82  template<template<typename...> class TList, typename... Ts>
83  using CartesianProduct = typename detail::CartesianProductImpl<TList, Ts...>::type;
84 } // namespace alpaka::meta
typename detail::ConcatenateImpl< T... >::type Concatenate
Definition: Concatenate.hpp:28
typename detail::CartesianProductImpl< TList, Ts... >::type CartesianProduct
typename CartesianProductImplHelper< TList< X... >, TList< Ts... > >::type type2
typename detail::CartesianProductImplHelper< TList< TList< Ts >... >, Tail... >::type type