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