Add bind_front_handler:

This works similarly to bind_handler, and can help with reducing
template instantiations and compiler memory usage (since it does
not need to support placeholders).

A specialization for the most common case `void(error_code, size_t)`
is provided to minimize instantiation cost.
This commit is contained in:
Vinnie Falco
2018-11-21 12:47:38 -08:00
parent 868ca0f470
commit d581bcc348
6 changed files with 575 additions and 80 deletions
+135 -52
View File
@@ -32,34 +32,7 @@ public:
}
};
#if 0
// This function should fail to compile
void
failStdBind()
{
std::bind(bind_handler(handler<>{}));
}
#endif
void
callback(int v)
{
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");
}
struct copyable_handler
struct copyable
{
template<class... Args>
void
@@ -68,44 +41,154 @@ public:
}
};
void
testAsioHandlerInvoke()
{
// make sure things compile, also can set a
// breakpoint in asio_handler_invoke to make sure
// it is instantiated.
boost::asio::io_context ioc;
boost::asio::io_service::strand s{ioc};
test::stream ts{ioc};
boost::asio::post(ioc.get_executor(),
s.wrap(copyable_handler{}));
}
struct move_only
{
move_only() = default;
move_only(move_only&&) = default;
move_only(move_only const&) = delete;
void operator()() const{};
};
void
testMoveOnly()
callback(int v)
{
bind_handler([](move_only){}, move_only{})();
bind_handler([](move_only){}, std::placeholders::_1)(move_only{});
bind_handler([](move_only, move_only){}, move_only{}, std::placeholders::_1)(move_only{});
BEAST_EXPECT(v == 42);
}
#if 0
// This function should fail to compile
void
failStdBind()
{
std::bind(bind_handler(handler<>{}));
}
void
failStdBindFront()
{
std::bind(bind_front_handler(handler<>{}));
}
#endif
void
testBindHandler()
{
// invocation
{
auto f = bind_handler(std::bind(
&bind_handler_test::callback, this,
std::placeholders::_1), 42);
f();
}
// placeholders
{
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");
}
// move-only
{
bind_handler([](move_only){}, move_only{})();
bind_handler([](move_only){}, std::placeholders::_1)(move_only{});
bind_handler([](move_only, move_only){}, move_only{}, std::placeholders::_1)(move_only{});
}
// asio_handler_invoke
{
// make sure things compile, also can set a
// breakpoint in asio_handler_invoke to make sure
// it is instantiated.
boost::asio::io_context ioc;
boost::asio::strand<
boost::asio::io_context::executor_type> s{
ioc.get_executor()};
test::stream ts{ioc};
boost::asio::post(s,
bind_handler(copyable{}, 42));
}
}
void
testBindFrontHandler()
{
// invocation
{
bind_front_handler(
std::bind(
&bind_handler_test::callback,
this,
42));
bind_front_handler(
std::bind(
&bind_handler_test::callback,
this,
std::placeholders::_1), 42);
bind_front_handler(
std::bind(
&bind_handler_test::callback,
this,
std::placeholders::_1))(42);
bind_front_handler(
bind_front_handler(
std::bind(
&bind_handler_test::callback,
this,
std::placeholders::_1)),
42);
bind_front_handler(
bind_front_handler(
std::bind(
&bind_handler_test::callback,
this,
std::placeholders::_1)))(42);
}
// move-only
{
bind_front_handler([]{});
}
// specializations
{
bind_front_handler(copyable{});
bind_front_handler(copyable{}, 1);
bind_front_handler(copyable{}, 1, 2);
bind_front_handler(copyable{}, 1, 2, 3);
bind_front_handler(copyable{}, 1, 2, 3, 4);
bind_front_handler(copyable{},
error_code{}, std::size_t(4));
}
// asio_handler_invoke
{
// make sure things compile, also can set a
// breakpoint in asio_handler_invoke to make sure
// it is instantiated.
boost::asio::io_context ioc;
boost::asio::strand<
boost::asio::io_context::executor_type> s{
ioc.get_executor()};
test::stream ts{ioc};
boost::asio::post(s,
bind_front_handler(copyable{}, 42));
}
}
void
run() override
{
auto f = bind_handler(std::bind(
&bind_handler_test::callback, this,
std::placeholders::_1), 42);
f();
testPlaceholders();
testAsioHandlerInvoke();
testMoveOnly();
testBindHandler();
testBindFrontHandler();
}
};