Decay bound arguments in handler wrapper parameters:

fix #1365

To reduce instantiations, the list of template parameters
to the bind and bind_front handler wrappers are decayed before
naming the class template.
This commit is contained in:
Vinnie Falco
2018-12-20 00:54:04 -08:00
parent f00237cb35
commit e7b8cc73a5
4 changed files with 72 additions and 21 deletions

View File

@ -1,3 +1,9 @@
Version 201
* Decay bound arguments in handler wrapper parameters
--------------------------------------------------------------------------------
Version 200 Version 200
* Don't include OpenSSL for core snippets * Don't include OpenSSL for core snippets

View File

@ -31,16 +31,19 @@ namespace beast {
handler, whose associated allocator and associated executor will handler, whose associated allocator and associated executor will
will be the same as those of the original handler. will be the same as those of the original handler.
Example: @par Example
This function posts the invocation of the specified completion
handler with bound arguments:
@code @code
template<class AsyncReadStream, class ReadHandler> template <class AsyncReadStream, class ReadHandler>
void void
signal_aborted(AsyncReadStream& stream, ReadHandler&& handler) signal_aborted (AsyncReadStream& stream, ReadHandler&& handler)
{ {
net::post( net::post(
stream.get_executor(), stream.get_executor(),
bind_handler(std::forward<ReadHandler>(handler), bind_handler (std::forward <ReadHandler> (handler),
net::error::operation_aborted, 0)); net::error::operation_aborted, 0));
} }
@endcode @endcode
@ -57,7 +60,8 @@ template<class Handler, class... Args>
__implementation_defined__ __implementation_defined__
#else #else
detail::bind_wrapper< detail::bind_wrapper<
typename std::decay<Handler>::type, Args...> typename std::decay<Handler>::type,
typename std::decay<Args>::type...>
#endif #endif
bind_handler(Handler&& handler, Args&&... args) bind_handler(Handler&& handler, Args&&... args)
{ {
@ -67,9 +71,11 @@ bind_handler(Handler&& handler, Args&&... args)
Handler, void(Args...)>::value, Handler, void(Args...)>::value,
"Handler requirements not met"); "Handler requirements not met");
#endif #endif
return detail::bind_wrapper<typename std::decay< return detail::bind_wrapper<
Handler>::type, Args...>(std::forward< typename std::decay<Handler>::type,
Handler>(handler), std::forward<Args>(args)...); typename std::decay<Args>::type...>(
std::forward<Handler>(handler),
std::forward<Args>(args)...);
} }
/** Bind parameters to a completion handler, creating a new handler. /** Bind parameters to a completion handler, creating a new handler.
@ -83,17 +89,20 @@ bind_handler(Handler&& handler, Args&&... args)
handler, whose associated allocator and associated executor will handler, whose associated allocator and associated executor will
will be the same as those of the original handler. will be the same as those of the original handler.
Example: @par Example
This function posts the invocation of the specified completion
handler with bound arguments:
@code @code
template<class AsyncReadStream, class ReadHandler> template <class AsyncReadStream, class ReadHandler>
void void
signal_aborted(AsyncReadStream& stream, ReadHandler&& handler) signal_eof (AsyncReadStream& stream, ReadHandler&& handler)
{ {
net::post( net::post(
stream.get_executor(), stream.get_executor(),
bind_front_handler(std::forward<ReadHandler>(handler), bind_front_handler (std::forward<ReadHandler> (handler),
net::error::operation_aborted, 0)); net::error::eof, 0));
} }
@endcode @endcode

View File

@ -31,8 +31,7 @@ namespace detail {
template<class Handler, class... Args> template<class Handler, class... Args>
class bind_wrapper class bind_wrapper
{ {
using args_type = detail::tuple< using args_type = detail::tuple<Args...>;
typename std::decay<Args>::type...>;
Handler h_; Handler h_;
args_type args_; args_type args_;
@ -84,9 +83,7 @@ class bind_wrapper
std::forward<Vals>(vals)); std::forward<Vals>(vals));
} }
template< template<class ArgsTuple, std::size_t... S>
class ArgsTuple,
std::size_t... S>
static static
void void
invoke( invoke(
@ -123,12 +120,15 @@ public:
bind_wrapper(bind_wrapper&&) = default; bind_wrapper(bind_wrapper&&) = default;
bind_wrapper(bind_wrapper const&) = default; bind_wrapper(bind_wrapper const&) = default;
template<class DeducedHandler> template<
class DeducedHandler,
class... Args_>
explicit explicit
bind_wrapper( bind_wrapper(
DeducedHandler&& handler, Args&&... args) DeducedHandler&& handler,
Args_&&... args)
: h_(std::forward<DeducedHandler>(handler)) : h_(std::forward<DeducedHandler>(handler))
, args_(std::forward<Args>(args)...) , args_(std::forward<Args_>(args)...)
{ {
} }

View File

@ -12,6 +12,7 @@
#include <boost/beast/core/detail/type_traits.hpp> #include <boost/beast/core/detail/type_traits.hpp>
#include <boost/beast/_experimental/unit_test/suite.hpp> #include <boost/beast/_experimental/unit_test/suite.hpp>
#include <boost/beast/_experimental/test/stream.hpp>
#include <boost/asio/io_context.hpp> #include <boost/asio/io_context.hpp>
#include <boost/asio/bind_executor.hpp> #include <boost/asio/bind_executor.hpp>
#include <boost/asio/executor_work_guard.hpp> #include <boost/asio/executor_work_guard.hpp>
@ -41,6 +42,40 @@ public:
} }
}; };
template <class AsyncReadStream, class ReadHandler>
void
signal_aborted (AsyncReadStream& stream, ReadHandler&& handler)
{
net::post(
stream.get_executor(),
bind_handler (std::forward <ReadHandler> (handler),
net::error::operation_aborted, 0));
}
template <class AsyncReadStream, class ReadHandler>
void
signal_eof (AsyncReadStream& stream, ReadHandler&& handler)
{
net::post(
stream.get_executor(),
bind_front_handler (std::forward<ReadHandler> (handler),
net::error::eof, 0));
}
void
testJavadocs()
{
BEAST_EXPECT((
&bind_handler_test::signal_aborted<
test::stream, handler<error_code, std::size_t>>));
BEAST_EXPECT((
&bind_handler_test::signal_eof<
test::stream, handler<error_code, std::size_t>>));
}
//--------------------------------------------------------------------------
struct copyable struct copyable
{ {
template<class... Args> template<class... Args>
@ -469,6 +504,7 @@ public:
void void
run() override run() override
{ {
testJavadocs();
testBindHandler(); testBindHandler();
testBindFrontHandler(); testBindFrontHandler();
} }