From e32c5c5e2888b7226438c67b4038a81ae31266c3 Mon Sep 17 00:00:00 2001 From: Ashish Sadanandan Date: Wed, 4 May 2016 00:12:51 -0600 Subject: [PATCH] `noexcept` specifications for `BOOST_STRONG_TYPEDEF` `BOOST_STRONG_TYPEDEF` now detects whether the type being wrapped is nothrow default/copy constructible and nothrow assignable. The wrapped type is given its own `noexcept` specifications accordingly. --- .../boost/serialization/strong_typedef.hpp | 36 +++++----- test/Jamfile.v2 | 3 + test/test_strong_typedef.cpp | 66 +++++++++++++++++++ 3 files changed, 89 insertions(+), 16 deletions(-) create mode 100644 test/test_strong_typedef.cpp diff --git a/include/boost/serialization/strong_typedef.hpp b/include/boost/serialization/strong_typedef.hpp index c1bf1844..c193fc07 100644 --- a/include/boost/serialization/strong_typedef.hpp +++ b/include/boost/serialization/strong_typedef.hpp @@ -10,6 +10,7 @@ // strong_typedef.hpp: // (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// (C) Copyright 2016 Ashish Sadanandan // Use, modification and distribution is subject to 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) @@ -24,23 +25,26 @@ #include #include +#include +#include +#include -#define BOOST_STRONG_TYPEDEF(T, D) \ -struct D \ - : boost::totally_ordered1< D \ - , boost::totally_ordered2< D, T \ - > > \ -{ \ - T t; \ - explicit D(const T t_) : t(t_) {}; \ - D(): t() {}; \ - D(const D & t_) : t(t_.t){} \ - D & operator=(const D & rhs) { t = rhs.t; return *this;} \ - D & operator=(const T & rhs) { t = rhs; return *this;} \ - operator const T & () const {return t; } \ - operator T & () { return t; } \ - bool operator==(const D & rhs) const { return t == rhs.t; } \ - bool operator<(const D & rhs) const { return t < rhs.t; } \ +#define BOOST_STRONG_TYPEDEF(T, D) \ +struct D \ + : boost::totally_ordered1< D \ + , boost::totally_ordered2< D, T \ + > > \ +{ \ + T t; \ + explicit D(const T& t_) BOOST_NOEXCEPT_IF(boost::has_nothrow_copy_constructor::value) : t(t_) {}; \ + D() BOOST_NOEXCEPT_IF(boost::has_nothrow_default_constructor::value) : t() {}; \ + D(const D & t_) BOOST_NOEXCEPT_IF(boost::has_nothrow_copy_constructor::value) : t(t_.t) {} \ + D& operator=(const D& rhs) BOOST_NOEXCEPT_IF(boost::has_nothrow_assign::value) {t = rhs.t; return *this;} \ + D& operator=(const T& rhs) BOOST_NOEXCEPT_IF(boost::has_nothrow_assign::value) {t = rhs; return *this;} \ + operator const T&() const {return t;} \ + operator T&() {return t;} \ + bool operator==(const D& rhs) const {return t == rhs.t;} \ + bool operator<(const D& rhs) const {return t < rhs.t;} \ }; #endif // BOOST_SERIALIZATION_STRONG_TYPEDEF_HPP diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 3f72d086..45d21788 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -123,6 +123,9 @@ test-suite "serialization" : [ test-bsl-run_polymorphic_archive test_polymorphic : test_polymorphic_A A ] [ test-bsl-run_polymorphic_archive test_polymorphic2 : test_polymorphic2imp ] [ test-bsl-run_polymorphic_archive test_polymorphic_helper ] + + # should compile + [ compile test_strong_typedef.cpp ] ; if ! $(BOOST_ARCHIVE_LIST) { diff --git a/test/test_strong_typedef.cpp b/test/test_strong_typedef.cpp new file mode 100644 index 00000000..42056642 --- /dev/null +++ b/test/test_strong_typedef.cpp @@ -0,0 +1,66 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// test_strong_typedef.cpp + +// (C) Copyright 2016 Ashish Sadanandan +// Use, modification and distribution is subject to 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) + +// should pass compilation + +#include +#include + +#include +#include +#include + +/////////////////////////////////////////////////////////////////////// +// Define a strong typedef for int. +// The new type should be nothrow constructible and assignable. + +BOOST_STRONG_TYPEDEF(int, strong_int) + +BOOST_STATIC_ASSERT(boost::has_nothrow_default_constructor::value); +BOOST_STATIC_ASSERT(boost::has_nothrow_copy_constructor::value); +BOOST_STATIC_ASSERT(boost::has_nothrow_assign::value); + + +/////////////////////////////////////////////////////////////////////// +// strong_int can now be placed in another type, which can also be +// nothrow constructible and assignable. + +struct type1 +{ + long some_long; + strong_int sint; +}; + +BOOST_STATIC_ASSERT(boost::has_nothrow_default_constructor::value); +BOOST_STATIC_ASSERT(boost::has_nothrow_copy_constructor::value); +BOOST_STATIC_ASSERT(boost::has_nothrow_assign::value); + + +/////////////////////////////////////////////////////////////////////// +// Now define a type that throws, and a strong_typedef for it +// The strong_typedef should also not have nothrow construction/assign. + +struct not_noexcept +{ + not_noexcept() {} + not_noexcept(not_noexcept const&) {} + not_noexcept& operator=(not_noexcept const&) {return *this;} + bool operator==(not_noexcept const&) const {return false;} + bool operator<(not_noexcept const&) const {return false;} +}; +BOOST_STRONG_TYPEDEF(not_noexcept, strong_not_noexcept) + +BOOST_STATIC_ASSERT(! boost::has_nothrow_default_constructor::value); +BOOST_STATIC_ASSERT(! boost::has_nothrow_copy_constructor::value); +BOOST_STATIC_ASSERT(! boost::has_nothrow_assign::value); + + +int main() +{ + return EXIT_SUCCESS; +}