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