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.
This commit is contained in:
Vinnie Falco
2016-10-10 08:28:12 -04:00
parent 2106f364f6
commit 0eb3605232
2 changed files with 86 additions and 44 deletions

View File

@ -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:

View File

@ -513,8 +513,11 @@ private:
bool
needs_eof(std::false_type) const;
template<class...>
using void_t = void;
template<class C>
class has_on_start_t
class check_on_start_t
{
template<class T, class R =
decltype(std::declval<T>().on_start(
@ -528,11 +531,11 @@ private:
static bool const value = type::value;
};
template<class C>
using has_on_start =
std::integral_constant<bool, has_on_start_t<C>::value>;
using check_on_start =
std::integral_constant<bool, check_on_start_t<C>::value>;
template<class C>
class has_on_method_t
class check_on_method_t
{
template<class T, class R =
decltype(std::declval<T>().on_method(
@ -547,11 +550,11 @@ private:
static bool const value = type::value;
};
template<class C>
using has_on_method =
std::integral_constant<bool, has_on_method_t<C>::value>;
using check_on_method =
std::integral_constant<bool, check_on_method_t<C>::value>;
template<class C>
class has_on_uri_t
class check_on_uri_t
{
template<class T, class R =
decltype(std::declval<T>().on_uri(
@ -566,11 +569,11 @@ private:
static bool const value = type::value;
};
template<class C>
using has_on_uri =
std::integral_constant<bool, has_on_uri_t<C>::value>;
using check_on_uri =
std::integral_constant<bool, check_on_uri_t<C>::value>;
template<class C>
class has_on_reason_t
class check_on_reason_t
{
template<class T, class R =
decltype(std::declval<T>().on_reason(
@ -585,11 +588,11 @@ private:
static bool const value = type::value;
};
template<class C>
using has_on_reason =
std::integral_constant<bool, has_on_reason_t<C>::value>;
using check_on_reason =
std::integral_constant<bool, check_on_reason_t<C>::value>;
template<class C>
class has_on_request_t
class check_on_request_t
{
template<class T, class R =
decltype(std::declval<T>().on_request(
@ -603,11 +606,11 @@ private:
static bool const value = type::value;
};
template<class C>
using has_on_request =
std::integral_constant<bool, has_on_request_t<C>::value>;
using check_on_request =
std::integral_constant<bool, check_on_request_t<C>::value>;
template<class C>
class has_on_response_t
class check_on_response_t
{
template<class T, class R =
decltype(std::declval<T>().on_response(
@ -621,11 +624,11 @@ private:
static bool const value = type::value;
};
template<class C>
using has_on_response =
std::integral_constant<bool, has_on_response_t<C>::value>;
using check_on_response =
std::integral_constant<bool, check_on_response_t<C>::value>;
template<class C>
class has_on_field_t
class check_on_field_t
{
template<class T, class R =
decltype(std::declval<T>().on_uri(
@ -640,11 +643,11 @@ private:
static bool const value = type::value;
};
template<class C>
using has_on_field =
std::integral_constant<bool, has_on_field_t<C>::value>;
using check_on_field =
std::integral_constant<bool, check_on_field_t<C>::value>;
template<class C>
class has_on_value_t
class check_on_value_t
{
template<class T, class R =
decltype(std::declval<T>().on_uri(
@ -659,11 +662,11 @@ private:
static bool const value = type::value;
};
template<class C>
using has_on_value =
std::integral_constant<bool, has_on_value_t<C>::value>;
using check_on_value =
std::integral_constant<bool, check_on_value_t<C>::value>;
template<class C>
class has_on_headers_t
class check_on_headers_t
{
template<class T, class R = std::is_convertible<body_what,
decltype(std::declval<T>().on_headers(
@ -676,11 +679,11 @@ private:
static bool const value = type::value;
};
template<class C>
using has_on_headers =
std::integral_constant<bool, has_on_headers_t<C>::value>;
using check_on_headers =
std::integral_constant<bool, check_on_headers_t<C>::value>;
template<class C>
class has_on_body_t
class check_on_body_t
{
template<class T, class R =
decltype(std::declval<T>().on_body(
@ -695,11 +698,11 @@ private:
static bool const value = type::value;
};
template<class C>
using has_on_body =
std::integral_constant<bool, has_on_body_t<C>::value>;
using check_on_body =
std::integral_constant<bool, check_on_body_t<C>::value>;
template<class C>
class has_on_complete_t
class check_on_complete_t
{
template<class T, class R =
decltype(std::declval<T>().on_complete(
@ -713,11 +716,15 @@ private:
static bool const value = type::value;
};
template<class C>
using has_on_complete =
std::integral_constant<bool, has_on_complete_t<C>::value>;
using check_on_complete =
std::integral_constant<bool, check_on_complete_t<C>::value>;
#undef BEAST_HAS_MEMBER
void call_on_start(error_code& ec, std::true_type)
{
static_assert(check_on_start<Derived>::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<Derived>{});
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<Derived>::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<bool,
isRequest && has_on_method<Derived>::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<Derived>::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<bool,
isRequest && has_on_uri<Derived>::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<Derived>::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<bool,
! isRequest && has_on_reason<Derived>::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<Derived>::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<bool,
isRequest && has_on_request<Derived>::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<Derived>::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<bool,
! isRequest && has_on_response<Derived>::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<Derived>::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<Derived>{});
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<Derived>::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<Derived>{});
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<Derived>::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<Derived>{});
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<Derived>::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<Derived>{});
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<Derived>::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<Derived>{});
call_on_complete(ec, std::is_member_function_pointer<
decltype(&Derived::on_complete)>{});
}
};