From 0eb36052321bf033e7059c1641f0d7cdf0b37e15 Mon Sep 17 00:00:00 2001 From: Vinnie Falco Date: Mon, 10 Oct 2016 08:28:12 -0400 Subject: [PATCH] Refactor base_parser_v1 callback traits: When the derived class provides a member function with the corresponding callback name, but the signature is different, a compile error will be generated instead of silently ignoring the member function. --- CHANGELOG.md | 1 + include/beast/http/basic_parser_v1.hpp | 129 ++++++++++++++++--------- 2 files changed, 86 insertions(+), 44 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 56a73e29..73ac9eb1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ * Constrain parser_v1 constructor * Improve first line serialization * Add pause option to on_headers interface +* Refactor base_parser_v1 callback traits: * Refine Parser concept API Changes: diff --git a/include/beast/http/basic_parser_v1.hpp b/include/beast/http/basic_parser_v1.hpp index b9425c49..317c607a 100644 --- a/include/beast/http/basic_parser_v1.hpp +++ b/include/beast/http/basic_parser_v1.hpp @@ -513,8 +513,11 @@ private: bool needs_eof(std::false_type) const; + template + using void_t = void; + template - class has_on_start_t + class check_on_start_t { template().on_start( @@ -528,11 +531,11 @@ private: static bool const value = type::value; }; template - using has_on_start = - std::integral_constant::value>; + using check_on_start = + std::integral_constant::value>; template - class has_on_method_t + class check_on_method_t { template().on_method( @@ -547,11 +550,11 @@ private: static bool const value = type::value; }; template - using has_on_method = - std::integral_constant::value>; + using check_on_method = + std::integral_constant::value>; template - class has_on_uri_t + class check_on_uri_t { template().on_uri( @@ -566,11 +569,11 @@ private: static bool const value = type::value; }; template - using has_on_uri = - std::integral_constant::value>; + using check_on_uri = + std::integral_constant::value>; template - class has_on_reason_t + class check_on_reason_t { template().on_reason( @@ -585,11 +588,11 @@ private: static bool const value = type::value; }; template - using has_on_reason = - std::integral_constant::value>; + using check_on_reason = + std::integral_constant::value>; template - class has_on_request_t + class check_on_request_t { template().on_request( @@ -603,11 +606,11 @@ private: static bool const value = type::value; }; template - using has_on_request = - std::integral_constant::value>; + using check_on_request = + std::integral_constant::value>; template - class has_on_response_t + class check_on_response_t { template().on_response( @@ -621,11 +624,11 @@ private: static bool const value = type::value; }; template - using has_on_response = - std::integral_constant::value>; + using check_on_response = + std::integral_constant::value>; template - class has_on_field_t + class check_on_field_t { template().on_uri( @@ -640,11 +643,11 @@ private: static bool const value = type::value; }; template - using has_on_field = - std::integral_constant::value>; + using check_on_field = + std::integral_constant::value>; template - class has_on_value_t + class check_on_value_t { template().on_uri( @@ -659,11 +662,11 @@ private: static bool const value = type::value; }; template - using has_on_value = - std::integral_constant::value>; + using check_on_value = + std::integral_constant::value>; template - class has_on_headers_t + class check_on_headers_t { template().on_headers( @@ -676,11 +679,11 @@ private: static bool const value = type::value; }; template - using has_on_headers = - std::integral_constant::value>; + using check_on_headers = + std::integral_constant::value>; template - class has_on_body_t + class check_on_body_t { template().on_body( @@ -695,11 +698,11 @@ private: static bool const value = type::value; }; template - using has_on_body = - std::integral_constant::value>; + using check_on_body = + std::integral_constant::value>; template - class has_on_complete_t + class check_on_complete_t { template().on_complete( @@ -713,11 +716,15 @@ private: static bool const value = type::value; }; template - using has_on_complete = - std::integral_constant::value>; + using check_on_complete = + std::integral_constant::value>; + +#undef BEAST_HAS_MEMBER void call_on_start(error_code& ec, std::true_type) { + static_assert(check_on_start::value, + "on_start requirements not met"); impl().on_start(ec); } @@ -727,12 +734,15 @@ private: void call_on_start(error_code& ec) { - call_on_start(ec, has_on_start{}); + call_on_start(ec, std::is_member_function_pointer< + decltype(&Derived::on_start)>{}); } void call_on_method(error_code& ec, boost::string_ref const& s, std::true_type) { + static_assert(check_on_method::value, + "on_method requirements not met"); impl().on_method(s, ec); } @@ -748,7 +758,8 @@ private: { h_left_ -= s.size(); call_on_method(ec, s, std::integral_constant::value>{}); + isRequest && std::is_member_function_pointer< + decltype(&Derived::on_method)>::value>{}); } else { @@ -759,6 +770,8 @@ private: void call_on_uri(error_code& ec, boost::string_ref const& s, std::true_type) { + static_assert(check_on_uri::value, + "on_uri requirements not met"); impl().on_uri(s, ec); } @@ -773,7 +786,8 @@ private: { h_left_ -= s.size(); call_on_uri(ec, s, std::integral_constant::value>{}); + isRequest && std::is_member_function_pointer< + decltype(&Derived::on_uri)>::value>{}); } else { @@ -784,6 +798,8 @@ private: void call_on_reason(error_code& ec, boost::string_ref const& s, std::true_type) { + static_assert(check_on_reason::value, + "on_reason requirements not met"); impl().on_reason(s, ec); } @@ -798,7 +814,8 @@ private: { h_left_ -= s.size(); call_on_reason(ec, s, std::integral_constant::value>{}); + ! isRequest && std::is_member_function_pointer< + decltype(&Derived::on_reason)>::value>{}); } else { @@ -808,6 +825,8 @@ private: void call_on_request(error_code& ec, std::true_type) { + static_assert(check_on_request::value, + "on_request requirements not met"); impl().on_request(ec); } @@ -818,11 +837,14 @@ private: void call_on_request(error_code& ec) { call_on_request(ec, std::integral_constant::value>{}); + isRequest && std::is_member_function_pointer< + decltype(&Derived::on_request)>::value>{}); } void call_on_response(error_code& ec, std::true_type) { + static_assert(check_on_response::value, + "on_response requirements not met"); impl().on_response(ec); } @@ -833,12 +855,15 @@ private: void call_on_response(error_code& ec) { call_on_response(ec, std::integral_constant::value>{}); + ! isRequest && std::is_member_function_pointer< + decltype(&Derived::on_response)>::value>{}); } void call_on_field(error_code& ec, boost::string_ref const& s, std::true_type) { + static_assert(check_on_field::value, + "on_field requirements not met"); impl().on_field(s, ec); } @@ -852,7 +877,9 @@ private: if(! h_max_ || s.size() <= h_left_) { h_left_ -= s.size(); - call_on_field(ec, s, has_on_field{}); + call_on_field(ec, s, + std::is_member_function_pointer< + decltype(&Derived::on_field)>{}); } else { @@ -863,6 +890,8 @@ private: void call_on_value(error_code& ec, boost::string_ref const& s, std::true_type) { + static_assert(check_on_value::value, + "on_value requirements not met"); impl().on_value(s, ec); } @@ -876,7 +905,9 @@ private: if(! h_max_ || s.size() <= h_left_) { h_left_ -= s.size(); - call_on_value(ec, s, has_on_value{}); + call_on_value(ec, s, + std::is_member_function_pointer< + decltype(&Derived::on_value)>{}); } else { @@ -888,6 +919,8 @@ private: call_on_headers(error_code& ec, std::uint64_t content_length, std::true_type) { + static_assert(check_on_headers::value, + "on_headers requirements not met"); return impl().on_headers(content_length, ec); } @@ -901,12 +934,15 @@ private: call_on_headers(error_code& ec) { return call_on_headers(ec, content_length_, - has_on_headers{}); + std::is_member_function_pointer< + decltype(&Derived::on_headers)>{}); } void call_on_body(error_code& ec, boost::string_ref const& s, std::true_type) { + static_assert(check_on_body::value, + "on_body requirements not met"); impl().on_body(s, ec); } @@ -920,7 +956,9 @@ private: if(! b_max_ || s.size() <= b_left_) { b_left_ -= s.size(); - call_on_body(ec, s, has_on_body{}); + call_on_body(ec, s, + std::is_member_function_pointer< + decltype(&Derived::on_body)>{}); } else { @@ -930,6 +968,8 @@ private: void call_on_complete(error_code& ec, std::true_type) { + static_assert(check_on_complete::value, + "on_complete requirements not met"); impl().on_complete(ec); } @@ -939,7 +979,8 @@ private: void call_on_complete(error_code& ec) { - call_on_complete(ec, has_on_complete{}); + call_on_complete(ec, std::is_member_function_pointer< + decltype(&Derived::on_complete)>{}); } };