mirror of
https://github.com/boostorg/beast.git
synced 2025-07-29 20:37:31 +02:00
bind_handler allows placeholders
This commit is contained in:
@ -3,6 +3,7 @@ Version 84:
|
||||
* Tidy up buffer_front
|
||||
* static_buffer::consume improvement
|
||||
* multi_buffer is type-check friendly
|
||||
* bind_handler allows placeholders
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
@ -18,11 +18,14 @@ namespace beast {
|
||||
|
||||
/** Bind parameters to a completion handler, creating a new handler.
|
||||
|
||||
This function creates a new handler which, when invoked with no
|
||||
parameters, calls the original handler with the list of bound
|
||||
arguments. The passed handler and arguments are forwarded into
|
||||
the returned handler, which provides the same `io_service`
|
||||
execution guarantees as the original handler.
|
||||
This function creates a new handler which, when invoked, calls
|
||||
the original handler with the list of bound arguments. Any
|
||||
parameters passed in the invocation will be subtituted for
|
||||
placeholders present in the list of bound arguments. Parameters
|
||||
which are not matched to placeholders are silently discarded.
|
||||
The passed handler and arguments are forwarded into the returned
|
||||
handler, which provides the same `io_service` execution guarantees
|
||||
as the original handler.
|
||||
|
||||
Unlike `boost::asio::io_service::wrap`, the returned handler can
|
||||
be used in a subsequent call to `boost::asio::io_service::post`
|
||||
@ -57,9 +60,11 @@ detail::bound_handler<
|
||||
#endif
|
||||
bind_handler(Handler&& handler, Args&&... args)
|
||||
{
|
||||
#if 0
|
||||
static_assert(is_completion_handler<
|
||||
Handler, void(Args...)>::value,
|
||||
"Handler requirements not met");
|
||||
#endif
|
||||
return detail::bound_handler<typename std::decay<
|
||||
Handler>::type, Args...>(std::forward<
|
||||
Handler>(handler), std::forward<Args>(args)...);
|
||||
|
@ -12,6 +12,8 @@
|
||||
#include <boost/asio/handler_alloc_hook.hpp>
|
||||
#include <boost/asio/handler_continuation_hook.hpp>
|
||||
#include <boost/asio/handler_invoke_hook.hpp>
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
|
||||
namespace beast {
|
||||
@ -32,16 +34,72 @@ private:
|
||||
Handler h_;
|
||||
args_type args_;
|
||||
|
||||
template<class Tuple, std::size_t... S>
|
||||
static void invoke(Handler& h, Tuple& args,
|
||||
template<class Arg, class Vals>
|
||||
static
|
||||
typename std::enable_if<
|
||||
std::is_placeholder<typename
|
||||
std::decay<Arg>::type>::value == 0,
|
||||
Arg&&>::type
|
||||
extract(Arg&& arg, Vals& vals)
|
||||
{
|
||||
return arg;
|
||||
}
|
||||
|
||||
template<class Arg, class Vals>
|
||||
static
|
||||
typename std::enable_if<
|
||||
std::is_placeholder<typename
|
||||
std::decay<Arg>::type>::value != 0,
|
||||
typename std::tuple_element<
|
||||
std::is_placeholder<
|
||||
typename std::decay<Arg>::type>::value - 1,
|
||||
Vals>::type&&>::type
|
||||
extract(Arg&&, Vals&& vals)
|
||||
{
|
||||
return std::get<std::is_placeholder<
|
||||
typename std::decay<Arg>::type>::value - 1>(
|
||||
std::forward<Vals>(vals));
|
||||
}
|
||||
|
||||
template<
|
||||
class ArgsTuple,
|
||||
std::size_t... S>
|
||||
static
|
||||
void
|
||||
invoke(
|
||||
Handler& h,
|
||||
ArgsTuple& args,
|
||||
std::tuple<>&&,
|
||||
index_sequence<S...>)
|
||||
{
|
||||
boost::ignore_unused(args);
|
||||
h(std::get<S>(args)...);
|
||||
}
|
||||
|
||||
template<
|
||||
class ArgsTuple,
|
||||
class ValsTuple,
|
||||
std::size_t... S>
|
||||
static
|
||||
void
|
||||
invoke(
|
||||
Handler& h,
|
||||
ArgsTuple& args,
|
||||
ValsTuple&& vals,
|
||||
index_sequence<S...>)
|
||||
{
|
||||
boost::ignore_unused(args);
|
||||
boost::ignore_unused(vals);
|
||||
h(extract(std::get<S>(args),
|
||||
std::forward<ValsTuple>(vals))...);
|
||||
}
|
||||
|
||||
public:
|
||||
using result_type = void;
|
||||
|
||||
bound_handler(bound_handler&&) = default;
|
||||
bound_handler(bound_handler const&) = default;
|
||||
|
||||
template<class DeducedHandler>
|
||||
explicit
|
||||
bound_handler(
|
||||
@ -51,17 +109,23 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
template<class... Values>
|
||||
void
|
||||
operator()()
|
||||
operator()(Values&&... values)
|
||||
{
|
||||
invoke(h_, args_,
|
||||
std::forward_as_tuple(
|
||||
std::forward<Values>(values)...),
|
||||
index_sequence_for<Args...>());
|
||||
}
|
||||
|
||||
template<class... Values>
|
||||
void
|
||||
operator()() const
|
||||
operator()(Values&&... values) const
|
||||
{
|
||||
invoke(h_, args_,
|
||||
std::forward_as_tuple(
|
||||
std::forward<Values>(values)...),
|
||||
index_sequence_for<Args...>());
|
||||
}
|
||||
|
||||
@ -107,8 +171,6 @@ public:
|
||||
} // detail
|
||||
} // beast
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace std {
|
||||
template<class Handler, class... Args>
|
||||
void
|
||||
|
@ -10,17 +10,20 @@
|
||||
|
||||
#include <beast/core/detail/type_traits.hpp>
|
||||
#include <beast/unit_test/suite.hpp>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
namespace beast {
|
||||
|
||||
class bind_handler_test : public unit_test::suite
|
||||
{
|
||||
public:
|
||||
template<class... Args>
|
||||
struct handler
|
||||
{
|
||||
void
|
||||
operator()() const;
|
||||
operator()(Args const&...) const
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
#if 0
|
||||
@ -28,7 +31,7 @@ public:
|
||||
void
|
||||
failStdBind()
|
||||
{
|
||||
std::bind(bind_handler(handler{}));
|
||||
std::bind(bind_handler(handler<>{}));
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -37,14 +40,27 @@ public:
|
||||
{
|
||||
BEAST_EXPECT(v == 42);
|
||||
}
|
||||
|
||||
void
|
||||
testPlaceholders()
|
||||
{
|
||||
namespace ph = std::placeholders;
|
||||
|
||||
bind_handler(handler<>{})();
|
||||
bind_handler(handler<int>{}, 1)();
|
||||
bind_handler(handler<int, std::string>{}, 1, "hello")();
|
||||
bind_handler(handler<int>{}, ph::_1)(1);
|
||||
bind_handler(handler<int, std::string>{}, ph::_1, ph::_2)(1, "hello");
|
||||
}
|
||||
|
||||
void run()
|
||||
void
|
||||
run() override
|
||||
{
|
||||
auto f = bind_handler(std::bind(
|
||||
&bind_handler_test::callback, this,
|
||||
std::placeholders::_1), 42);
|
||||
f();
|
||||
pass();
|
||||
testPlaceholders();
|
||||
}
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user