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
* Don't include OpenSSL for core snippets

View File

@ -31,16 +31,19 @@ namespace beast {
handler, whose associated allocator and associated executor will
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
template<class AsyncReadStream, class ReadHandler>
template <class AsyncReadStream, class ReadHandler>
void
signal_aborted(AsyncReadStream& stream, ReadHandler&& handler)
signal_aborted (AsyncReadStream& stream, ReadHandler&& handler)
{
net::post(
stream.get_executor(),
bind_handler(std::forward<ReadHandler>(handler),
bind_handler (std::forward <ReadHandler> (handler),
net::error::operation_aborted, 0));
}
@endcode
@ -57,7 +60,8 @@ template<class Handler, class... Args>
__implementation_defined__
#else
detail::bind_wrapper<
typename std::decay<Handler>::type, Args...>
typename std::decay<Handler>::type,
typename std::decay<Args>::type...>
#endif
bind_handler(Handler&& handler, Args&&... args)
{
@ -67,9 +71,11 @@ bind_handler(Handler&& handler, Args&&... args)
Handler, void(Args...)>::value,
"Handler requirements not met");
#endif
return detail::bind_wrapper<typename std::decay<
Handler>::type, Args...>(std::forward<
Handler>(handler), std::forward<Args>(args)...);
return detail::bind_wrapper<
typename std::decay<Handler>::type,
typename std::decay<Args>::type...>(
std::forward<Handler>(handler),
std::forward<Args>(args)...);
}
/** 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
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
template<class AsyncReadStream, class ReadHandler>
template <class AsyncReadStream, class ReadHandler>
void
signal_aborted(AsyncReadStream& stream, ReadHandler&& handler)
signal_eof (AsyncReadStream& stream, ReadHandler&& handler)
{
net::post(
stream.get_executor(),
bind_front_handler(std::forward<ReadHandler>(handler),
net::error::operation_aborted, 0));
bind_front_handler (std::forward<ReadHandler> (handler),
net::error::eof, 0));
}
@endcode

View File

@ -31,8 +31,7 @@ namespace detail {
template<class Handler, class... Args>
class bind_wrapper
{
using args_type = detail::tuple<
typename std::decay<Args>::type...>;
using args_type = detail::tuple<Args...>;
Handler h_;
args_type args_;
@ -84,9 +83,7 @@ class bind_wrapper
std::forward<Vals>(vals));
}
template<
class ArgsTuple,
std::size_t... S>
template<class ArgsTuple, std::size_t... S>
static
void
invoke(
@ -123,12 +120,15 @@ public:
bind_wrapper(bind_wrapper&&) = default;
bind_wrapper(bind_wrapper const&) = default;
template<class DeducedHandler>
template<
class DeducedHandler,
class... Args_>
explicit
bind_wrapper(
DeducedHandler&& handler, Args&&... args)
DeducedHandler&& handler,
Args_&&... args)
: 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/_experimental/unit_test/suite.hpp>
#include <boost/beast/_experimental/test/stream.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/bind_executor.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
{
template<class... Args>
@ -469,6 +504,7 @@ public:
void
run() override
{
testJavadocs();
testBindHandler();
testBindFrontHandler();
}