Add http::is_fields trait

fix #515
This commit is contained in:
Vinnie Falco
2017-06-19 18:16:02 -07:00
parent 56a561da9a
commit 5613ce7e97
8 changed files with 131 additions and 0 deletions

View File

@ -7,6 +7,7 @@ Version 62:
* Tidy up namespaces in examples
* Clear the error faster
* Avoid explicit operator bool for error
* Add http::is_fields trait
API Changes:

View File

@ -115,6 +115,13 @@ In this table:
Transfer-Encoding field if the field is present ahd chunked is the
last encoding.
]
][
[`is_fields<X>`]
[`std::true_type`]
[
An alias for `std::true_type` for `X`, otherwise an alias
for `std::false_type`.
]
]
]

View File

@ -96,6 +96,7 @@
<member><link linkend="beast.ref.beast__http__is_body">is_body</link></member>
<member><link linkend="beast.ref.beast__http__is_body_writer">is_body_writer</link></member>
<member><link linkend="beast.ref.beast__http__is_body_reader">is_body_reader</link></member>
<member><link linkend="beast.ref.beast__http__is_fields">is_fields</link></member>
</simplelist>
<bridgehead renderas="sect3">Concepts</bridgehead>
<simplelist type="vert" columns="1">

View File

@ -9,6 +9,8 @@
#define BEAST_HTTP_DETAIL_TYPE_TRAITS_HPP
#include <beast/core/detail/type_traits.hpp>
#include <boost/optional.hpp>
#include <cstdint>
namespace beast {
namespace http {
@ -49,6 +51,15 @@ struct fields_model
string_view method() const;
string_view reason() const;
string_view target() const;
protected:
void set_method_impl(string_view s);
void set_target_impl(string_view s);
void set_reason_impl(string_view s);
string_view get_method_impl() const;
string_view get_target_impl() const;
string_view get_reason_impl() const;
void prepare_payload_impl(bool b, boost::optional<std::uint64_t> n);
};
template<class T, class = beast::detail::void_t<>>
@ -75,6 +86,67 @@ struct is_body_sized<T, beast::detail::void_t<
T::size(std::declval<typename T::value_type const&>()),
(void)0)>> : std::true_type {};
template<class T>
struct is_fields_helper : T
{
template<class U = is_fields_helper>
static auto f1(int) -> decltype(
void(std::declval<U&>().set_method_impl(std::declval<string_view>())),
std::true_type());
static auto f1(...) -> std::false_type;
using t1 = decltype(f1(0));
template<class U = is_fields_helper>
static auto f2(int) -> decltype(
void(std::declval<U&>().set_target_impl(std::declval<string_view>())),
std::true_type());
static auto f2(...) -> std::false_type;
using t2 = decltype(f2(0));
template<class U = is_fields_helper>
static auto f3(int) -> decltype(
void(std::declval<U&>().set_reason_impl(std::declval<string_view>())),
std::true_type());
static auto f3(...) -> std::false_type;
using t3 = decltype(f3(0));
template<class U = is_fields_helper>
static auto f4(int) -> decltype(
std::declval<string_view&>() = std::declval<U&>().get_method_impl(),
std::true_type());
static auto f4(...) -> std::false_type;
using t4 = decltype(f4(0));
template<class U = is_fields_helper>
static auto f5(int) -> decltype(
std::declval<string_view&>() = std::declval<U&>().get_target_impl(),
std::true_type());
static auto f5(...) -> std::false_type;
using t5 = decltype(f5(0));
template<class U = is_fields_helper>
static auto f6(int) -> decltype(
std::declval<string_view&>() = std::declval<U&>().get_reason_impl(),
std::true_type());
static auto f6(...) -> std::false_type;
using t6 = decltype(f6(0));
template<class U = is_fields_helper>
static auto f7(int) -> decltype(
void(std::declval<U&>().prepare_payload_impl(
std::declval<bool>(),
std::declval<boost::optional<std::uint64_t>>())),
std::true_type());
static auto f7(...) -> std::false_type;
using t7 = decltype(f7(0));
using type = std::integral_constant<bool,
t1::value && t2::value && t3::value &&
t4::value && t5::value && t6::value &&
t7::value
>;
};
} // detail
} // http
} // beast

View File

@ -48,6 +48,9 @@ template<class Fields>
struct header<true, Fields> : Fields
#endif
{
static_assert(is_fields<Fields>::value,
"Fields requirements not met");
/// Indicates if the header is a request or response.
#if BEAST_DOXYGEN
using is_request = isRequest;
@ -196,6 +199,9 @@ private:
template<class Fields>
struct header<false, Fields> : Fields
{
static_assert(is_fields<Fields>::value,
"Fields requirements not met");
/// Indicates if the header is a request or response.
using is_request = std::false_type;

View File

@ -137,6 +137,39 @@ struct is_body_writer<T, beast::detail::void_t<decltype(
};
#endif
/** Determine if `T` meets the requirements of @b Fields
@tparam T The body type to test.
@par Example
Use with `static_assert`:
@code
template<bool isRequest, class Body, class Fields>
void f(message<isRequest, Body, Fields> const&)
{
static_assert(is_fields<Fields>::value,
"Fields requirements not met");
...
@endcode
Use with `std::enable_if` (SFINAE):
@code
template<bool isRequest, class Body, class Fields>
typename std::enable_if<is_fields<Fields>::value>::type
f(message<isRequest, Body, Fields> const&);
@endcode
*/
#if BEAST_DOXYGEN
template<class T>
struct is_fields : std::integral_constant<bool, ...> {};
#else
template<class T>
using is_fields = typename detail::is_fields_helper<T>::type;
#endif
} // http
} // beast

View File

@ -10,6 +10,7 @@
#include <beast/http/empty_body.hpp>
#include <beast/http/message.hpp>
#include <beast/http/type_traits.hpp>
#include <beast/test/test_allocator.hpp>
#include <beast/unit_test/suite.hpp>
#include <boost/lexical_cast.hpp>
@ -17,6 +18,8 @@
namespace beast {
namespace http {
BOOST_STATIC_ASSERT(is_fields<fields>::value);
class fields_test : public beast::unit_test::suite
{
public:

View File

@ -20,5 +20,13 @@ BOOST_STATIC_ASSERT(is_body_reader<empty_body>::value);
BOOST_STATIC_ASSERT(! is_body_writer<std::string>::value);
namespace {
struct not_fields {};
} // (anonymous)
BOOST_STATIC_ASSERT(! is_fields<not_fields>::value);
} // http
} // beast