From 190d20e3a83c14f03bec5b2ac17566971bff4fa8 Mon Sep 17 00:00:00 2001 From: Damian Jarek Date: Sat, 18 Nov 2017 19:50:57 +0100 Subject: [PATCH] Tidy up basic_fields exception specifiers fix #894 Signed-off-by: Damian Jarek --- CHANGELOG.md | 4 ++ include/boost/beast/http/fields.hpp | 33 +++++++------- include/boost/beast/http/impl/fields.ipp | 11 +++-- test/beast/http/fields.cpp | 57 +++++++++++++++++++++++- 4 files changed, 83 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c0c7f025..b85e9b8f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ Version 147: * Don't use boost::string_ref * Use iterator wrapper in detail::buffers_range +HTTP: + +* Tidy up basic_fields exception specifiers + WebSocket: * control callback is copied or moved diff --git a/include/boost/beast/http/fields.hpp b/include/boost/beast/http/fields.hpp index 469320ca..1fe95684 100644 --- a/include/boost/beast/http/fields.hpp +++ b/include/boost/beast/http/fields.hpp @@ -188,6 +188,19 @@ private: boost::intrusive::constant_time_size, boost::intrusive::compare>::type; + using align_type = typename + boost::type_with_alignment::type; + + using rebind_type = typename + beast::detail::allocator_traits:: + template rebind_alloc; + + using alloc_traits = + beast::detail::allocator_traits; + + using size_type = typename + beast::detail::allocator_traits::size_type; + public: /// Destructor @@ -201,14 +214,14 @@ public: @param alloc The allocator to use. */ explicit - basic_fields(Allocator const& alloc); + basic_fields(Allocator const& alloc) noexcept; /** Move constructor. The state of the moved-from object is as if constructed using the same allocator. */ - basic_fields(basic_fields&&); + basic_fields(basic_fields&&) noexcept; /** Move constructor. @@ -245,7 +258,8 @@ public: The state of the moved-from object is as if constructed using the same allocator. */ - basic_fields& operator=(basic_fields&&); + basic_fields& operator=(basic_fields&&) noexcept( + alloc_traits::propagate_on_container_move_assignment::value); /// Copy assignment. basic_fields& operator=(basic_fields const&); @@ -690,19 +704,6 @@ private: template friend class basic_fields; - using align_type = typename - boost::type_with_alignment::type; - - using rebind_type = typename - beast::detail::allocator_traits:: - template rebind_alloc; - - using alloc_traits = - beast::detail::allocator_traits; - - using size_type = typename - beast::detail::allocator_traits::size_type; - value_type& new_element(field name, string_view sname, string_view value); diff --git a/include/boost/beast/http/impl/fields.ipp b/include/boost/beast/http/impl/fields.ipp index d0505f0b..0e3d48ec 100644 --- a/include/boost/beast/http/impl/fields.ipp +++ b/include/boost/beast/http/impl/fields.ipp @@ -349,14 +349,14 @@ basic_fields:: template basic_fields:: -basic_fields(Allocator const& alloc) +basic_fields(Allocator const& alloc) noexcept : beast::detail::empty_base_optimization(alloc) { } template basic_fields:: -basic_fields(basic_fields&& other) +basic_fields(basic_fields&& other) noexcept : beast::detail::empty_base_optimization( std::move(other.member())) , set_(std::move(other.set_)) @@ -426,9 +426,12 @@ basic_fields(basic_fields const& other, template auto basic_fields:: -operator=(basic_fields&& other) -> - basic_fields& +operator=(basic_fields&& other) noexcept( + alloc_traits::propagate_on_container_move_assignment::value) + -> basic_fields& { + static_assert(is_nothrow_move_assignable::value, + "Allocator must be noexcept assignable."); if(this == &other) return *this; move_assign(other, std::integral_constant::value); - class fields_test : public beast::unit_test::suite { public: + template + class test_allocator + { + public: + using value_type = T; + + test_allocator() noexcept(false) {} + + template ::value>::type> + test_allocator(test_allocator const&) noexcept {} + + value_type* + allocate(std::size_t n) + { + return static_cast(::operator new (n*sizeof(value_type))); + } + + void + deallocate(value_type* p, std::size_t) noexcept + { + ::operator delete(p); + } + + template + friend + bool + operator==(test_allocator const&, test_allocator const&) noexcept + { + return true; + } + + template + friend + bool + operator!=(test_allocator const& x, test_allocator const& y) noexcept + { + return !(x == y); + } + }; + + using test_fields = basic_fields>; + + BOOST_STATIC_ASSERT(is_fields::value); + BOOST_STATIC_ASSERT(is_fields::value); + + // std::allocator is noexcept movable, fields should satisfy + // these constraints as well. + BOOST_STATIC_ASSERT(std::is_nothrow_move_constructible::value); + BOOST_STATIC_ASSERT(std::is_nothrow_move_assignable::value); + + // Check if basic_fields respects throw-constructibility and + // propagate_on_container_move_assignment of the allocator. + BOOST_STATIC_ASSERT(std::is_nothrow_move_constructible::value); + BOOST_STATIC_ASSERT(!std::is_nothrow_move_assignable::value); + template using fa_t = basic_fields;