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 #include <ctti/type_id.hpp>
12 
13 namespace cpp
14 {
15 
16 namespace detail
17 {
18 
19 template<typename T>
20 class DefaultConstructible
21 {
22 public:
23  constexpr DefaultConstructible() = default;
24 
25  using type = T;
26 };
27 
28 template<typename Function, typename Arg, typename... Args>
29 void foreach(Function function, Arg&& arg, Args&&... args)
30 {
31  [](...){}(
32  (function(std::forward<Arg>(arg)), 0),
33  (function(std::forward<Args>(args)), 0)...
34  );
35 }
36 
37 template<typename Function>
38 void foreach(Function)
39 {}
40 
41 }
42 
43 template<typename Arg>
44 auto foreach(Arg&& arg)
45 {
46  return [arg](auto function)
47  {
48  return function(arg);
49  };
50 }
51 
52 template<typename Arg, typename Arg2, typename... Args>
53 auto foreach(Arg&& arg, Arg2&& arg2, Args&&... args)
54 {
55  return [arg, arg2, args...](auto function)
56  {
57  ::cpp::detail::foreach(function, arg, arg2, args...);
58  };
59 }
60 
61 inline auto foreach()
62 {
63  return [](auto){};
64 }
65 
66 namespace
67 {
68  template<typename Ts>
69  class TypesCall;
70 
71  template<typename T, typename... Ts>
72  class TypesCall<cpp::meta::list<T, Ts...>>
73  {
74  public:
75  template<typename Function>
76  static void apply_void(Function function)
77  {
78  ::cpp::foreach(
79  detail::DefaultConstructible<T>(),
80  detail::DefaultConstructible<Ts>()...
81  )(function);
82  }
83 
84  template<typename U, typename Function>
85  static std::vector<U> apply(Function function)
86  {
87  return {
88  function(detail::DefaultConstructible<T>()),
89  function(detail::DefaultConstructible<Ts>())...
90  };
91  }
92 
93  template<typename Function>
94  static auto apply(Function function)
95  {
96  return std::make_tuple(
97  function(detail::DefaultConstructible<T>()),
98  function(detail::DefaultConstructible<Ts>())...
99  );
100  }
101  };
102 
103  template<>
104  class TypesCall<cpp::meta::list<>>
105  {
106  public:
107  template<typename Function>
108  static void apply_void(Function function)
109  {}
110 
111  template<typename T, typename Function>
112  static std::vector<T> apply(Function function)
113  {
114  return {};
115  }
116 
117  template<typename Function>
118  static auto apply(Function function)
119  {
120  return std::make_tuple();
121  }
122  };
123 
124  template<typename... Ts>
125  class TypesCall<cpp::meta::list<cpp::meta::list<Ts...>>> :
126  public TypesCall<meta::list<Ts...>>
127  {};
128 }
129 
130 template<typename T, typename... Ts, typename Function>
131 std::vector<T> types_call(Function function)
132 {
133  return TypesCall<cpp::meta::list<Ts...>>::template apply<T>(function);
134 }
135 
136 template<typename... Ts, typename Function>
137 void foreach_type(Function function)
138 {
139  TypesCall<cpp::meta::list<Ts...>>::apply_void(function);
140 }
141 
142 template<typename Function, typename Previous>
143 auto fold(Function function, Previous&& previous)
144 {
145  return std::forward<Previous>(previous);
146 }
147 
148 template<typename Function, typename Previous, typename Head, typename... Tail>
149 auto fold(Function function, Previous&& previous, Head&& head, Tail&&... tail)
150 {
151  return fold(
152  function,
153  function(
154  std::forward<Previous>(previous),
155  std::forward<Head>(head)
156  ),
157  std::forward<Tail>(tail)...
158  );
159 }
160 
161 template<typename T, typename Function, typename... Args>
162 std::vector<T> fmap(Function function, Args&&... args)
163 {
164  return {function(std::forward<Args>(args))...};
165 }
166 
167 template<typename T, typename... Ts, typename Function>
168 std::vector<T> fmap(Function function)
169 {
170  return types_call<T, Ts...>(function);
171 }
172 
173 template<typename Types>
174 std::string printTypeList()
175 {
176  std::ostringstream os;
177 
178  os << "{";
179 
180  foreach<Types>([&os](auto type)
181  {
182  os << ctti::type_id<typename decltype(type)::type>().name() << ", ";
183  });
184 
185  os << "}";
186 
187  return os.str();
188 }
189 
190 }
191 
192 #endif // SIPLASPLAS_UTILITY_FUSION_HPP
Definition: canary_allocator.hpp:7