From 4e1ab4e7718a14d4cf043cc9c3f85395bd46e34b Mon Sep 17 00:00:00 2001 From: Yauheni Akhotnikau Date: Fri, 29 Nov 2019 19:10:48 +0300 Subject: [PATCH] A fix for issue #64. --- dev/restinio/cmake/target.cmake | 2 +- dev/restinio/compiler_features.hpp | 66 ++++++++++++++++++++++ dev/restinio/impl/response_coordinator.hpp | 22 +++++--- 3 files changed, 81 insertions(+), 9 deletions(-) diff --git a/dev/restinio/cmake/target.cmake b/dev/restinio/cmake/target.cmake index 87dd8370..ed1724c8 100644 --- a/dev/restinio/cmake/target.cmake +++ b/dev/restinio/cmake/target.cmake @@ -1 +1 @@ -set(RESTINIO_VERSION "0.6.1") +set(RESTINIO_VERSION "0.6.1.1") diff --git a/dev/restinio/compiler_features.hpp b/dev/restinio/compiler_features.hpp index f78fa3b9..f899f523 100644 --- a/dev/restinio/compiler_features.hpp +++ b/dev/restinio/compiler_features.hpp @@ -105,3 +105,69 @@ #define RESTINIO_STATIC_ASSERT_NOT_NOEXCEPT(expr) \ static_assert(!noexcept(expr), #expr " is not expected to be noexcept" ) +namespace restinio +{ + +namespace static_if_details +{ + +template< bool Condition > +struct static_if_impl; + +template<> +struct static_if_impl +{ + template + static decltype(auto) + call( If_Part && if_part, Else_Part && ) + { + return if_part(); + } +}; + +template<> +struct static_if_impl +{ + template + static decltype(auto) + call( If_Part &&, Else_Part && else_part ) + { + return else_part(); + } +}; + +} /* namespace static_if_details */ + +// +// static_if_else +// +/*! + * @brief An emulation of if constexpr for C++14. + * + * Usage example: + * @code + * static_if_else< noexcept(some-expression) >( + * []() noexcept { + * ... // Some action that doesn't throw. + * }, + * [] { + * try { + * ... // Some action that throws. + * } + * catch(...) {} + * }); + * @endcode + * + * @since v.0.6.1.1 + */ +template< bool Condition, typename If_Part, typename Else_Part > +decltype(auto) +static_if_else( If_Part && if_part, Else_Part && else_part ) +{ + return static_if_details::static_if_impl::call( + std::forward(if_part), + std::forward(else_part) ); +} + +} /* namespace restinio */ + diff --git a/dev/restinio/impl/response_coordinator.hpp b/dev/restinio/impl/response_coordinator.hpp index 543220c8..6dc5c0f2 100644 --- a/dev/restinio/impl/response_coordinator.hpp +++ b/dev/restinio/impl/response_coordinator.hpp @@ -91,14 +91,20 @@ class response_context_t write_group_t result{ std::move( m_write_groups.front() ) }; - // We expect that m_write_groups.erase() isn't noexpect - // and because of that this call should be done via - // suppress_exceptions_quietly. - RESTINIO_STATIC_ASSERT_NOT_NOEXCEPT( - m_write_groups.erase(m_write_groups.begin()) ); - restinio::utils::suppress_exceptions_quietly( [this] { - m_write_groups.erase( begin( m_write_groups ) ); - } ); + // Some STL implementation can have std::vector::erase that + // doesn't throw. So we use a kind of static if to select + // an appropriate behaviour. + static_if_else< noexcept(m_write_groups.erase(m_write_groups.begin())) >( + // This is for the case when std::vector::erase doesn't throw. + [this]() noexcept { + m_write_groups.erase( m_write_groups.begin() ); + }, + // This is for the case when std::vector::erase does throw. + [this]() { + restinio::utils::suppress_exceptions_quietly( [this] { + m_write_groups.erase( m_write_groups.begin() ); + } ); + } ); return result; }