From d1bfa8e7b00f7c539d1074ec7f4e690376c9b66f Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sat, 26 Apr 2014 15:11:35 +0400 Subject: [PATCH] Added a new macro BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT, which implements a noexcept operator. Also added explicit noexcept specification for the constexpr macro. --- doc/explicit_operator_bool.qbk | 8 +- .../boost/utility/explicit_operator_bool.hpp | 31 ++++++- index.html | 2 +- test/Jamfile.v2 | 1 + test/explicit_operator_bool.cpp | 4 +- test/explicit_operator_bool_noexcept.cpp | 89 +++++++++++++++++++ 6 files changed, 123 insertions(+), 12 deletions(-) create mode 100644 test/explicit_operator_bool_noexcept.cpp diff --git a/doc/explicit_operator_bool.qbk b/doc/explicit_operator_bool.qbk index 4a7e4b1..64c5be4 100644 --- a/doc/explicit_operator_bool.qbk +++ b/doc/explicit_operator_bool.qbk @@ -5,7 +5,7 @@ / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) /] -[article BOOST_EXPLICIT_OPERATOR_BOOL and BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL +[article BOOST_EXPLICIT_OPERATOR_BOOL, BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT and BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL [quickbook 1.5] [authors [Semashev, Andrey]] [copyright 2013 Andrey Semashev] @@ -20,7 +20,7 @@ [section Overview] [/===============] -`BOOST_EXPLICIT_OPERATOR_BOOL()` and `BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL()` are compatibility helper macros that expand to an explicit conversion operator to `bool`. For compilers not supporting explicit conversion operators introduced in C++11 the macros expand to a conversion operator that implements the [@http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Safe_bool safe bool idiom]. In case if the compiler is not able to handle safe bool idiom well the macros expand to a regular conversion operator to `bool`. +`BOOST_EXPLICIT_OPERATOR_BOOL()`, `BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()` and `BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL()` are compatibility helper macros that expand to an explicit conversion operator to `bool`. For compilers not supporting explicit conversion operators introduced in C++11 the macros expand to a conversion operator that implements the [@http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Safe_bool safe bool idiom]. In case if the compiler is not able to handle safe bool idiom well the macros expand to a regular conversion operator to `bool`. [endsect] @@ -62,7 +62,3 @@ Now `my_ptr` can be used in conditional expressions, similarly to a regular poin * The macro was extracted from Boost.Log. [endsect] - - - - diff --git a/include/boost/utility/explicit_operator_bool.hpp b/include/boost/utility/explicit_operator_bool.hpp index 650caff..e16f34d 100644 --- a/include/boost/utility/explicit_operator_bool.hpp +++ b/include/boost/utility/explicit_operator_bool.hpp @@ -38,6 +38,19 @@ return !this->operator! ();\ } +/*! + * \brief The macro defines a noexcept explicit operator of conversion to \c bool + * + * The macro should be used inside the definition of a class that has to + * support the conversion. The class should also implement operator!, + * in terms of which the conversion operator will be implemented. + */ +#define BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()\ + BOOST_FORCEINLINE explicit operator bool () const BOOST_NOEXCEPT\ + {\ + return !this->operator! ();\ + } + /*! * \brief The macro defines a constexpr explicit operator of conversion to \c bool * @@ -46,7 +59,7 @@ * in terms of which the conversion operator will be implemented. */ #define BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL()\ - BOOST_FORCEINLINE BOOST_CONSTEXPR explicit operator bool () const\ + BOOST_FORCEINLINE BOOST_CONSTEXPR explicit operator bool () const BOOST_NOEXCEPT\ {\ return !this->operator! ();\ } @@ -101,8 +114,14 @@ namespace detail { return (!this->operator! () ? &boost::detail::unspecified_bool::true_value : (boost::detail::unspecified_bool_type)0);\ } +#define BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()\ + BOOST_FORCEINLINE operator boost::detail::unspecified_bool_type () const BOOST_NOEXCEPT\ + {\ + return (!this->operator! () ? &boost::detail::unspecified_bool::true_value : (boost::detail::unspecified_bool_type)0);\ + } + #define BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL()\ - BOOST_FORCEINLINE BOOST_CONSTEXPR operator boost::detail::unspecified_bool_type () const\ + BOOST_FORCEINLINE BOOST_CONSTEXPR operator boost::detail::unspecified_bool_type () const BOOST_NOEXCEPT\ {\ return (!this->operator! () ? &boost::detail::unspecified_bool::true_value : (boost::detail::unspecified_bool_type)0);\ } @@ -115,8 +134,14 @@ namespace detail { return !this->operator! ();\ } +#define BOOST_EXPLICIT_OPERATOR_BOOL()\ + BOOST_FORCEINLINE operator bool () const BOOST_NOEXCEPT\ + {\ + return !this->operator! ();\ + } + #define BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL()\ - BOOST_FORCEINLINE BOOST_CONSTEXPR operator bool () const\ + BOOST_FORCEINLINE BOOST_CONSTEXPR operator bool () const BOOST_NOEXCEPT\ {\ return !this->operator! ();\ } diff --git a/index.html b/index.html index e92da2a..d38b541 100644 --- a/index.html +++ b/index.html @@ -34,7 +34,7 @@ utility
string_ref
value_init
- BOOST_EXPLICIT_OPERATOR_BOOL and BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL + BOOST_EXPLICIT_OPERATOR_BOOL, BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT and BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL


diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index acf6329..b120ee3 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -47,6 +47,7 @@ test-suite utility [ compile-fail ../initialized_test_fail1.cpp ] [ compile-fail ../initialized_test_fail2.cpp ] [ run explicit_operator_bool.cpp ] + [ run explicit_operator_bool_noexcept.cpp ] [ compile-fail explicit_operator_bool_compile_fail_conv_int.cpp ] [ compile-fail explicit_operator_bool_compile_fail_conv_pvoid.cpp ] [ compile-fail explicit_operator_bool_compile_fail_delete.cpp ] diff --git a/test/explicit_operator_bool.cpp b/test/explicit_operator_bool.cpp index 07dd01b..5e85259 100644 --- a/test/explicit_operator_bool.cpp +++ b/test/explicit_operator_bool.cpp @@ -5,7 +5,7 @@ * http://www.boost.org/LICENSE_1_0.txt) */ /*! - * \file explicit_operator_bool_compile.cpp + * \file explicit_operator_bool.cpp * \author Andrey Semashev * \date 17.07.2010 * @@ -13,7 +13,7 @@ * the valid contexts. */ -#define BOOST_TEST_MODULE explicit_operator_bool_compile +#define BOOST_TEST_MODULE explicit_operator_bool #include diff --git a/test/explicit_operator_bool_noexcept.cpp b/test/explicit_operator_bool_noexcept.cpp new file mode 100644 index 0000000..c645cca --- /dev/null +++ b/test/explicit_operator_bool_noexcept.cpp @@ -0,0 +1,89 @@ +/* + * Copyright Andrey Semashev 2007 - 2013. + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + */ +/*! + * \file explicit_operator_bool_noexcept.cpp + * \author Andrey Semashev + * \date 26.04.2014 + * + * \brief This test checks that explicit operator bool is noexcept when possible. + */ + +#define BOOST_TEST_MODULE explicit_operator_bool_noexcept + +#include + +#if !defined(BOOST_NO_CXX11_NOEXCEPT) + +#include +#include + +namespace { + + struct checkable1 + { + BOOST_EXPLICIT_OPERATOR_BOOL() + bool operator! () const + { + return false; + } + }; + + struct checkable2 + { + BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL() + BOOST_CONSTEXPR bool operator! () const + { + return false; + } + }; + + struct noexcept_checkable1 + { + BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() + bool operator! () const noexcept + { + return false; + } + }; + + struct noexcept_checkable2 + { + BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL() + BOOST_CONSTEXPR bool operator! () const noexcept + { + return false; + } + }; + +} // namespace + +int main(int, char*[]) +{ + checkable1 val1; + checkable2 val2; + + noexcept_checkable1 noexcept_val1; + noexcept_checkable2 noexcept_val2; + + BOOST_TEST(!noexcept(static_cast< bool >(val1))); + // constexpr functions are implicitly noexcept + BOOST_TEST(noexcept(static_cast< bool >(val2))); + + BOOST_TEST(noexcept(static_cast< bool >(noexcept_val1))); + BOOST_TEST(noexcept(static_cast< bool >(noexcept_val2))); + + return boost::report_errors(); +} + +#else + +int main(int, char*[]) +{ + return 0; +} + +#endif