Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r84373 - in trunk: boost/unordered libs/unordered/test/unordered
From: dnljms_at_[hidden]
Date: 2013-05-19 10:30:13


Author: danieljames
Date: 2013-05-19 10:30:12 EDT (Sun, 19 May 2013)
New Revision: 84373
URL: http://svn.boost.org/trac/boost/changeset/84373

Log:
Add conditional `noexcept` for move constructors.

Also added `noexcept` for destructors because of a gcc bug, see:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56191

Found via:

http://stackoverflow.com/questions/15721544/destructors-and-noexcept
Added:
   trunk/libs/unordered/test/unordered/noexcept_tests.cpp (contents, props changed)
Text files modified:
   trunk/boost/unordered/unordered_map.hpp | 12 ++++++++----
   trunk/boost/unordered/unordered_set.hpp | 12 ++++++++----
   trunk/libs/unordered/test/unordered/Jamfile.v2 | 1 +
   3 files changed, 17 insertions(+), 8 deletions(-)

Modified: trunk/boost/unordered/unordered_map.hpp
==============================================================================
--- trunk/boost/unordered/unordered_map.hpp (original)
+++ trunk/boost/unordered/unordered_map.hpp 2013-05-19 10:30:12 EDT (Sun, 19 May 2013)
@@ -117,11 +117,13 @@
 
 #if defined(BOOST_UNORDERED_USE_MOVE)
         unordered_map(BOOST_RV_REF(unordered_map) other)
+ BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
             : table_(other.table_, boost::unordered::detail::move_tag())
         {
         }
 #elif !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
         unordered_map(unordered_map&& other)
+ BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
             : table_(other.table_, boost::unordered::detail::move_tag())
         {
         }
@@ -142,7 +144,7 @@
 
         // Destructor
 
- ~unordered_map();
+ ~unordered_map() BOOST_NOEXCEPT;
 
         // Assign
 
@@ -598,11 +600,13 @@
 
 #if defined(BOOST_UNORDERED_USE_MOVE)
         unordered_multimap(BOOST_RV_REF(unordered_multimap) other)
+ BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
             : table_(other.table_, boost::unordered::detail::move_tag())
         {
         }
 #elif !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
         unordered_multimap(unordered_multimap&& other)
+ BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
             : table_(other.table_, boost::unordered::detail::move_tag())
         {
         }
@@ -623,7 +627,7 @@
 
         // Destructor
 
- ~unordered_multimap();
+ ~unordered_multimap() BOOST_NOEXCEPT;
 
         // Assign
 
@@ -1057,7 +1061,7 @@
     }
     
     template <class K, class T, class H, class P, class A>
- unordered_map<K,T,H,P,A>::~unordered_map() {}
+ unordered_map<K,T,H,P,A>::~unordered_map() BOOST_NOEXCEPT {}
 
     template <class K, class T, class H, class P, class A>
     unordered_map<K,T,H,P,A>::unordered_map(
@@ -1390,7 +1394,7 @@
     }
     
     template <class K, class T, class H, class P, class A>
- unordered_multimap<K,T,H,P,A>::~unordered_multimap() {}
+ unordered_multimap<K,T,H,P,A>::~unordered_multimap() BOOST_NOEXCEPT {}
 
     template <class K, class T, class H, class P, class A>
     unordered_multimap<K,T,H,P,A>::unordered_multimap(

Modified: trunk/boost/unordered/unordered_set.hpp
==============================================================================
--- trunk/boost/unordered/unordered_set.hpp (original)
+++ trunk/boost/unordered/unordered_set.hpp 2013-05-19 10:30:12 EDT (Sun, 19 May 2013)
@@ -115,11 +115,13 @@
 
 #if defined(BOOST_UNORDERED_USE_MOVE)
         unordered_set(BOOST_RV_REF(unordered_set) other)
+ BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
             : table_(other.table_, boost::unordered::detail::move_tag())
         {
         }
 #elif !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
         unordered_set(unordered_set&& other)
+ BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
             : table_(other.table_, boost::unordered::detail::move_tag())
         {
         }
@@ -140,7 +142,7 @@
 
         // Destructor
 
- ~unordered_set();
+ ~unordered_set() BOOST_NOEXCEPT;
 
         // Assign
 
@@ -582,11 +584,13 @@
 
 #if defined(BOOST_UNORDERED_USE_MOVE)
         unordered_multiset(BOOST_RV_REF(unordered_multiset) other)
+ BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
             : table_(other.table_, boost::unordered::detail::move_tag())
         {
         }
 #elif !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
         unordered_multiset(unordered_multiset&& other)
+ BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
             : table_(other.table_, boost::unordered::detail::move_tag())
         {
         }
@@ -607,7 +611,7 @@
 
         // Destructor
 
- ~unordered_multiset();
+ ~unordered_multiset() BOOST_NOEXCEPT;
 
         // Assign
 
@@ -1032,7 +1036,7 @@
     }
     
     template <class T, class H, class P, class A>
- unordered_set<T,H,P,A>::~unordered_set() {}
+ unordered_set<T,H,P,A>::~unordered_set() BOOST_NOEXCEPT {}
 
     template <class T, class H, class P, class A>
     unordered_set<T,H,P,A>::unordered_set(
@@ -1316,7 +1320,7 @@
     }
     
     template <class T, class H, class P, class A>
- unordered_multiset<T,H,P,A>::~unordered_multiset() {}
+ unordered_multiset<T,H,P,A>::~unordered_multiset() BOOST_NOEXCEPT {}
 
     template <class T, class H, class P, class A>
     unordered_multiset<T,H,P,A>::unordered_multiset(

Modified: trunk/libs/unordered/test/unordered/Jamfile.v2
==============================================================================
--- trunk/libs/unordered/test/unordered/Jamfile.v2 (original)
+++ trunk/libs/unordered/test/unordered/Jamfile.v2 2013-05-19 10:30:12 EDT (Sun, 19 May 2013)
@@ -25,6 +25,7 @@
         [ run minimal_allocator.cpp ]
         [ run compile_set.cpp ]
         [ run compile_map.cpp ]
+ [ run noexcept_tests.cpp ]
         [ run link_test_1.cpp link_test_2.cpp ]
         [ run incomplete_test.cpp ]
         [ run simple_tests.cpp ]

Added: trunk/libs/unordered/test/unordered/noexcept_tests.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/unordered/test/unordered/noexcept_tests.cpp 2013-05-19 10:30:12 EDT (Sun, 19 May 2013)
@@ -0,0 +1,125 @@
+
+// Copyright 2013 Daniel James.
+// 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)
+#define private public
+#include "../helpers/prefix.hpp"
+#include <boost/unordered_set.hpp>
+#include <boost/unordered_map.hpp>
+#include "../helpers/postfix.hpp"
+
+#include "../helpers/test.hpp"
+
+namespace noexcept_tests
+{
+ // Test the noexcept is set correctly for the move constructor.
+
+ struct hash_possible_exception : boost::hash<int>
+ {
+ hash_possible_exception(hash_possible_exception const&) {}
+ };
+
+ struct equal_to_possible_exception : std::equal_to<int>
+ {
+ equal_to_possible_exception(equal_to_possible_exception const&) {}
+ };
+
+ UNORDERED_AUTO_TEST(test_noexcept)
+ {
+#if !defined(BOOST_NO_CXX11_NOEXCEPT)
+ BOOST_TEST((boost::is_nothrow_move_constructible<
+ boost::unordered_set<int> >::value));
+ BOOST_TEST((boost::is_nothrow_move_constructible<
+ boost::unordered_multiset<int> >::value));
+ BOOST_TEST((boost::is_nothrow_move_constructible<
+ boost::unordered_map<int, int> >::value));
+ BOOST_TEST((boost::is_nothrow_move_constructible<
+ boost::unordered_multimap<int, int> >::value));
+#endif
+
+ BOOST_TEST((!boost::is_nothrow_move_constructible<
+ boost::unordered_set<int, hash_possible_exception>
+ >::value));
+ BOOST_TEST((!boost::is_nothrow_move_constructible<
+ boost::unordered_multiset<int, boost::hash<int>,
+ equal_to_possible_exception>
+ >::value));
+ }
+
+ // Test that the move constructor does actually move without throwing
+ // an exception when it claims to.
+
+ struct test_exception {};
+
+ bool throwing_test_exception = false;
+ void test_throw(char const* name) {
+ if (throwing_test_exception) {
+ std::cerr << "Throw exception in: " << name << std::endl;
+ throw test_exception();
+ }
+ }
+
+ class hash_nothrow_move : boost::hash<int>
+ {
+ BOOST_COPYABLE_AND_MOVABLE(hash_nothrow_move)
+
+ typedef boost::hash<int> base;
+ public:
+ hash_nothrow_move(BOOST_RV_REF(hash_nothrow_move))
+ BOOST_NOEXCEPT {}
+
+ hash_nothrow_move() { test_throw("Constructor"); }
+ hash_nothrow_move(hash_nothrow_move const& x) { test_throw("Copy"); }
+ hash_nothrow_move& operator=(hash_nothrow_move const&)
+ { test_throw("Assign"); return *this; }
+ std::size_t operator()(int x) const
+ { test_throw("Operator"); return static_cast<base const&>(*this)(x); }
+ };
+
+ class equal_to_nothrow_move : std::equal_to<int>
+ {
+ BOOST_COPYABLE_AND_MOVABLE(equal_to_nothrow_move)
+
+ typedef std::equal_to<int> base;
+ public:
+ equal_to_nothrow_move(BOOST_RV_REF(equal_to_nothrow_move))
+ BOOST_NOEXCEPT {}
+ equal_to_nothrow_move() { test_throw("Constructor"); }
+ equal_to_nothrow_move(equal_to_nothrow_move const& x)
+ { test_throw("Copy"); }
+ equal_to_nothrow_move& operator=(equal_to_nothrow_move const&)
+ { test_throw("Assign"); return *this; }
+ std::size_t operator()(int x, int y) const
+ { test_throw("Operator"); return static_cast<base const&>(*this)(x, y); }
+ };
+
+ UNORDERED_AUTO_TEST(test_no_throw_when_noexcept)
+ {
+ typedef boost::unordered_set<int,
+ hash_nothrow_move, equal_to_nothrow_move> throwing_set;
+
+ if (boost::is_nothrow_move_constructible<throwing_set>::value)
+ {
+ throwing_test_exception = false;
+
+ throwing_set x1;
+ x1.insert(10);
+ x1.insert(50);
+
+
+ try {
+ throwing_test_exception = true;
+
+ throwing_set x2 = boost::move(x1);
+ BOOST_TEST(x2.size() == 2);
+ BOOST_TEST(*x2.begin() == 10 || *x2.begin() == 50);
+ } catch(test_exception) {
+ BOOST_TEST(false);
+ }
+
+ throwing_test_exception = false;
+ }
+ }
+}
+
+RUN_TESTS()


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk