Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion include/mp/proxy-types.h
Original file line number Diff line number Diff line change
Expand Up @@ -645,7 +645,8 @@ template <typename LocalType, typename Input>
void ThrowField(TypeList<LocalType>, InvokeContext& invoke_context, Input&& input)
{
ReadField(
TypeList<LocalType>(), invoke_context, input, ReadDestEmplace(TypeList<LocalType>(), ThrowFn<LocalType>()));
TypeList<LocalType>(), invoke_context, input, ReadDestEmplace(TypeList<LocalType>(),
[](auto&& ...args) -> const LocalType& { throw LocalType{std::forward<decltype(args)>(args)...}; }));
}

//! Special case for generic std::exception. It's an abstract type so it can't
Expand Down
155 changes: 1 addition & 154 deletions include/mp/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,39 +21,7 @@

namespace mp {

//! Generic utility functions used by capnp code. This mostly consists of
//! helpers that work around lack of C++14 functionality in C++11. This file
//! puts all C++14 workarounds in one place, so if/when bitcoin decides to
//! decides to upgrade to C++14, code can be accordingly simplified.
//!
//! C++14 has two features that really simplify generic programming. One is
//! auto-returning functions
//! (http://en.cppreference.com/w/cpp/language/template_argument_deduction#auto-returning_functions):
//!
//! auto DoSomething(Arg arg) {
//! return expression(arg);
//! }
//!
//! which in c++11 has to be written:
//!
//! auto DoSomething(Arg arg) -> decltype(expression(arg)) {
//! return expression(arg);
//! }
//!
//! Another is generic lambdas (http://en.cppreference.com/w/cpp/language/lambda):
//!
//! [capture](auto arg) { do_something(arg); }
//!
//! which in c++11 has to be written like
//!
//! struct DoSomething {
//! Capture m_capture;
//!
//! template<typename Arg>
//! void operator()(Arg arg) {
//! return do_something(arg);
//! }
//! };
//! Generic utility functions used by capnp code.

//! Type holding a list of types.
//!
Expand All @@ -79,127 +47,6 @@ Class<Types..., typename std::remove_reference<Args>::type...> Make(Args&&... ar
return Class<Types..., typename std::remove_reference<Args>::type...>{std::forward<Args>(args)...};
}

//! Function object composing two other function objects. Can be replaced with
//! auto lambdas when we update to C++14.
//!
//! Example:
//! Make<ComposeFn>(sin, atan2)(3, 4) == sin(atan2(3, 4))
template <typename Fn1, typename Fn2>
struct ComposeFn
{
Fn1&& fn1;
Fn2&& fn2;

template <typename... Args>
decltype(auto) operator()(Args&&... args) { return this->fn1(this->fn2(std::forward<Args>(args)...)); }
};

//! Bound function. See Bind() below.
template <typename Fn, typename BindArgs, typename BoundArgs = TypeList<>>
struct BoundFn;

//! Specialization of above for base case.
template <typename Fn, typename... BoundArgs>
struct BoundFn<Fn, TypeList<>, TypeList<BoundArgs...>>
{
Fn&& m_fn;

template <typename... FreeArgs>
decltype(auto) operator()(BoundArgs&... bound_args, FreeArgs&&... free_args)
{
return this->m_fn(bound_args..., std::forward<FreeArgs>(free_args)...);
}
};

//! Specialization of above for recursive case.
template <typename Fn, typename BindArg, typename... BindArgs, typename... BoundArgs>
struct BoundFn<Fn, TypeList<BindArg, BindArgs...>, TypeList<BoundArgs...>>
: BoundFn<Fn, TypeList<BindArgs...>, TypeList<BoundArgs..., BindArg>>
{
using Base = BoundFn<Fn, TypeList<BindArgs...>, TypeList<BoundArgs..., BindArg>>;
BindArg& m_bind_arg;

BoundFn(Fn& fn, BindArg& bind_arg, BindArgs&... bind_args) : Base{fn, bind_args...}, m_bind_arg(bind_arg) {}

// Use std::result_of instead of decltype return to work around gcc bug
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83249
template <typename... FreeArgs>
auto operator()(BoundArgs&... bound_args, FreeArgs&&... free_args) ->
typename std::result_of<Base(BoundArgs&..., BindArg&, FreeArgs...)>::type
{
return Base::operator()(bound_args..., m_bind_arg, std::forward<FreeArgs>(free_args)...);
}
};

//! std::bind replacement. Unlike std::bind it doesn't copy the function object
//! or argument but instead takes rvalue references. This allows it to work with
//! uncopyable objects, but also limits its use to situations where objects
//! don't go out of scope. Uses of this can be replaced with auto lambdas when
//! we update to C++14.
//!
//! Example:
//! Bind(atan2, 3)(4) == atan2(3, 4)
//!
//! Possible TODO: It might be nice to make binding more consistent with composing
//! and switch to calling syntax Make<Bind>(...) instead of Bind(...).
template <typename Fn, typename... BindArgs>
BoundFn<Fn, TypeList<BindArgs...>> Bind(Fn&& fn, BindArgs&... bind_args)
{
return {fn, bind_args...};
}

//! Bound tuple function. See BindTuple() below.
//!
//! C++14 equivalent:
//!
//! BoundTupleFn = [&fn](auto&&... params) { fn(std::forward_as_tuple(params...)); };
template <typename Fn>
struct BoundTupleFn
{
Fn& m_fn;
template <typename... Params>
decltype(auto) operator()(Params&&... params) { return this->m_fn(std::forward_as_tuple(params...)); }
};

//! Bind tuple argument to function. Arguments passed to the returned function
//! object are grouped together and passed to the wrapped function object as a
//! single forward_as_tuple argument.
template <typename Fn>
BoundTupleFn<Fn> BindTuple(Fn&& fn)
{
return {fn};
}

//! Function object wrapping std::get. Can be replaced with auto lambdas when we
//! update to C++14.
//!
//! Example:
//! GetFn<3>()(a) // Equivalent to std::get<3>(a)
template <std::size_t I>
struct GetFn
{
template <typename Tuple>
auto operator()(Tuple&& tuple) -> decltype(std::get<I>(tuple))&
{
return std::get<I>(tuple);
}
};

//! Function object that throws an exception. Can be replaced with auto lambdas
//! when we update to C++14.
//!
//! Example:
//! ThrowFn<E>()(args) // Equivalent to: throw E(args)
template <typename Exception>
struct ThrowFn
{
template <typename... Params>
const Exception& operator()(Params&&... params)
{
throw Exception(std::forward<Params>(params)...);
}
};

//! Type helper splitting a TypeList into two halves at position index.
//!
//! Example:
Expand Down