siplasplas
A library for C++ reflection and introspection
fusion.hpp
1 #ifndef SIPLASPLAS_UTILITY_FUSION_HPP
2 #define SIPLASPLAS_UTILITY_FUSION_HPP
3 
4 #include "tuple.hpp"
5 #include "meta.hpp"
6 
7 #include <bitset>
8 #include <sstream>
9 #include <vector>
10 
11 namespace cpp
12 {
13 
14 namespace detail
15 {
16 
17 template<typename T>
18 class DefaultConstructible
19 {
20 public:
21  constexpr DefaultConstructible() = default;
22 
23  using type = T;
24 };
25 
26 template<typename Function, typename Arg, typename... Args>
27 void foreach(Function function, Arg&& arg, Args&&... args)
28 {
29  [](...){}(
30  (function(std::forward<Arg>(arg)), 0),
31  (function(std::forward<Args>(args)), 0)...
32  );
33 }
34 
35 template<typename Function>
36 void foreach(Function)
37 {}
38 
39 }
40 
41 template<typename Arg>
42 auto foreach(Arg&& arg)
43 {
44  return [arg](auto function)
45  {
46  return function(arg);
47  };
48 }
49 
50 template<typename Arg, typename Arg2, typename... Args>
51 auto foreach(Arg&& arg, Arg2&& arg2, Args&&... args)
52 {
53  return [arg, arg2, args...](auto function)
54  {
55  ::cpp::detail::foreach(function, arg, arg2, args...);
56  };
57 }
58 
59 inline auto foreach()
60 {
61  return [](auto){};
62 }
63 
64 namespace
65 {
66  template<typename Ts>
67  class TypesCall;
68 
69  template<typename T, typename... Ts>
70  class TypesCall<cpp::meta::list<T, Ts...>>
71  {
72  public:
73  template<typename Function>
74  static void apply_void(Function function)
75  {
76  ::cpp::foreach(
77  detail::DefaultConstructible<T>(),
78  detail::DefaultConstructible<Ts>()...
79  )(function);
80  }
81 
82  template<typename U, typename Function>
83  static std::vector<U> apply(Function function)
84  {
85  return {
86  function(detail::DefaultConstructible<T>()),
87  function(detail::DefaultConstructible<Ts>())...
88  };
89  }
90 
91  template<typename Function>
92  static auto apply(Function function)
93  {
94  return std::make_tuple(
95  function(detail::DefaultConstructible<T>()),
96  function(detail::DefaultConstructible<Ts>())...
97  );
98  }
99  };
100 
101  template<>
102  class TypesCall<cpp::meta::list<>>
103  {
104  public:
105  template<typename Function>
106  static void apply_void(Function function)
107  {}
108 
109  template<typename T, typename Function>
110  static std::vector<T> apply(Function function)
111  {
112  return {};
113  }
114 
115  template<typename Function>
116  static auto apply(Function function)
117  {
118  return std::make_tuple();
119  }
120  };
121 
122  template<typename... Ts>
123  class TypesCall<cpp::meta::list<cpp::meta::list<Ts...>>> :
124  public TypesCall<meta::list<Ts...>>
125  {};
126 }
127 
128 template<typename T, typename... Ts, typename Function>
129 std::vector<T> types_call(Function function)
130 {
131  return TypesCall<cpp::meta::list<Ts...>>::template apply<T>(function);
132 }
133 
134 template<typename... Ts, typename Function>
135 void foreach_type(Function function)
136 {
137  TypesCall<cpp::meta::list<Ts...>>::apply_void(function);
138 }
139 
140 template<typename Function, typename Previous>
141 auto fold(Function function, Previous&& previous)
142 {
143  return std::forward<Previous>(previous);
144 }
145 
146 template<typename Function, typename Previous, typename Head, typename... Tail>
147 auto fold(Function function, Previous&& previous, Head&& head, Tail&&... tail)
148 {
149  return fold(
150  function,
151  function(
152  std::forward<Previous>(previous),
153  std::forward<Head>(head)
154  ),
155  std::forward<Tail>(tail)...
156  );
157 }
158 
159 template<typename T, typename Function, typename... Args>
160 std::vector<T> fmap(Function function, Args&&... args)
161 {
162  return {function(std::forward<Args>(args))...};
163 }
164 
165 template<typename T, typename... Ts, typename Function>
166 std::vector<T> fmap(Function function)
167 {
168  return types_call<T, Ts...>(function);
169 }
170 
171 }
172 
173 #endif // SIPLASPLAS_UTILITY_FUSION_HPP
Definition: canary_allocator.hpp:7