2121
2222namespace mp {
2323
24- // ! Generic utility functions used by capnp code. This mostly consists of
25- // ! helpers that work around lack of C++14 functionality in C++11. This file
26- // ! puts all C++14 workarounds in one place, so if/when bitcoin decides to
27- // ! decides to upgrade to C++14, code can be accordingly simplified.
28- // !
29- // ! C++14 has two features that really simplify generic programming. One is
30- // ! auto-returning functions
31- // ! (http://en.cppreference.com/w/cpp/language/template_argument_deduction#auto-returning_functions):
32- // !
33- // ! auto DoSomething(Arg arg) {
34- // ! return expression(arg);
35- // ! }
36- // !
37- // ! which in c++11 has to be written:
38- // !
39- // ! auto DoSomething(Arg arg) -> decltype(expression(arg)) {
40- // ! return expression(arg);
41- // ! }
42- // !
43- // ! Another is generic lambdas (http://en.cppreference.com/w/cpp/language/lambda):
44- // !
45- // ! [capture](auto arg) { do_something(arg); }
46- // !
47- // ! which in c++11 has to be written like
48- // !
49- // ! struct DoSomething {
50- // ! Capture m_capture;
51- // !
52- // ! template<typename Arg>
53- // ! void operator()(Arg arg) {
54- // ! return do_something(arg);
55- // ! }
56- // ! };
24+ // ! Generic utility functions used by capnp code.
5725
5826// ! Type holding a list of types.
5927// !
@@ -79,127 +47,6 @@ Class<Types..., typename std::remove_reference<Args>::type...> Make(Args&&... ar
7947 return Class<Types..., typename std::remove_reference<Args>::type...>{std::forward<Args>(args)...};
8048}
8149
82- // ! Function object composing two other function objects. Can be replaced with
83- // ! auto lambdas when we update to C++14.
84- // !
85- // ! Example:
86- // ! Make<ComposeFn>(sin, atan2)(3, 4) == sin(atan2(3, 4))
87- template <typename Fn1, typename Fn2>
88- struct ComposeFn
89- {
90- Fn1&& fn1;
91- Fn2&& fn2;
92-
93- template <typename ... Args>
94- decltype (auto ) operator ()(Args&&... args) { return this ->fn1 (this ->fn2 (std::forward<Args>(args)...)); }
95- };
96-
97- // ! Bound function. See Bind() below.
98- template <typename Fn, typename BindArgs, typename BoundArgs = TypeList<>>
99- struct BoundFn ;
100-
101- // ! Specialization of above for base case.
102- template <typename Fn, typename ... BoundArgs>
103- struct BoundFn <Fn, TypeList<>, TypeList<BoundArgs...>>
104- {
105- Fn&& m_fn;
106-
107- template <typename ... FreeArgs>
108- decltype (auto ) operator ()(BoundArgs&... bound_args, FreeArgs&&... free_args)
109- {
110- return this ->m_fn (bound_args..., std::forward<FreeArgs>(free_args)...);
111- }
112- };
113-
114- // ! Specialization of above for recursive case.
115- template <typename Fn, typename BindArg, typename ... BindArgs, typename ... BoundArgs>
116- struct BoundFn <Fn, TypeList<BindArg, BindArgs...>, TypeList<BoundArgs...>>
117- : BoundFn<Fn, TypeList<BindArgs...>, TypeList<BoundArgs..., BindArg>>
118- {
119- using Base = BoundFn<Fn, TypeList<BindArgs...>, TypeList<BoundArgs..., BindArg>>;
120- BindArg& m_bind_arg;
121-
122- BoundFn (Fn& fn, BindArg& bind_arg, BindArgs&... bind_args) : Base{fn, bind_args...}, m_bind_arg(bind_arg) {}
123-
124- // Use std::result_of instead of decltype return to work around gcc bug
125- // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83249
126- template <typename ... FreeArgs>
127- auto operator ()(BoundArgs&... bound_args, FreeArgs&&... free_args) ->
128- typename std::result_of<Base(BoundArgs&..., BindArg&, FreeArgs...)>::type
129- {
130- return Base::operator ()(bound_args..., m_bind_arg, std::forward<FreeArgs>(free_args)...);
131- }
132- };
133-
134- // ! std::bind replacement. Unlike std::bind it doesn't copy the function object
135- // ! or argument but instead takes rvalue references. This allows it to work with
136- // ! uncopyable objects, but also limits its use to situations where objects
137- // ! don't go out of scope. Uses of this can be replaced with auto lambdas when
138- // ! we update to C++14.
139- // !
140- // ! Example:
141- // ! Bind(atan2, 3)(4) == atan2(3, 4)
142- // !
143- // ! Possible TODO: It might be nice to make binding more consistent with composing
144- // ! and switch to calling syntax Make<Bind>(...) instead of Bind(...).
145- template <typename Fn, typename ... BindArgs>
146- BoundFn<Fn, TypeList<BindArgs...>> Bind (Fn&& fn, BindArgs&... bind_args)
147- {
148- return {fn, bind_args...};
149- }
150-
151- // ! Bound tuple function. See BindTuple() below.
152- // !
153- // ! C++14 equivalent:
154- // !
155- // ! BoundTupleFn = [&fn](auto&&... params) { fn(std::forward_as_tuple(params...)); };
156- template <typename Fn>
157- struct BoundTupleFn
158- {
159- Fn& m_fn;
160- template <typename ... Params>
161- decltype (auto ) operator ()(Params&&... params) { return this ->m_fn (std::forward_as_tuple (params...)); }
162- };
163-
164- // ! Bind tuple argument to function. Arguments passed to the returned function
165- // ! object are grouped together and passed to the wrapped function object as a
166- // ! single forward_as_tuple argument.
167- template <typename Fn>
168- BoundTupleFn<Fn> BindTuple (Fn&& fn)
169- {
170- return {fn};
171- }
172-
173- // ! Function object wrapping std::get. Can be replaced with auto lambdas when we
174- // ! update to C++14.
175- // !
176- // ! Example:
177- // ! GetFn<3>()(a) // Equivalent to std::get<3>(a)
178- template <std::size_t I>
179- struct GetFn
180- {
181- template <typename Tuple>
182- auto operator ()(Tuple&& tuple) -> decltype(std::get<I>(tuple))&
183- {
184- return std::get<I>(tuple);
185- }
186- };
187-
188- // ! Function object that throws an exception. Can be replaced with auto lambdas
189- // ! when we update to C++14.
190- // !
191- // ! Example:
192- // ! ThrowFn<E>()(args) // Equivalent to: throw E(args)
193- template <typename Exception>
194- struct ThrowFn
195- {
196- template <typename ... Params>
197- const Exception& operator ()(Params&&... params)
198- {
199- throw Exception (std::forward<Params>(params)...);
200- }
201- };
202-
20350// ! Type helper splitting a TypeList into two halves at position index.
20451// !
20552// ! Example:
0 commit comments