]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | |
2 | // Copyright 2013 Daniel James. | |
3 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | |
4 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
5 | ||
b32b8144 | 6 | // clang-format off |
7c673cae FG |
7 | #include "../helpers/prefix.hpp" |
8 | #include <boost/unordered_set.hpp> | |
9 | #include <boost/unordered_map.hpp> | |
10 | #include "../helpers/postfix.hpp" | |
b32b8144 | 11 | // clang-format on |
7c673cae FG |
12 | |
13 | #include "../helpers/test.hpp" | |
14 | ||
b32b8144 FG |
15 | namespace noexcept_tests { |
16 | // Test the noexcept is set correctly for the move constructor. | |
17 | ||
18 | struct hash_possible_exception : boost::hash<int> | |
19 | { | |
20 | hash_possible_exception(hash_possible_exception const&) {} | |
21 | }; | |
22 | ||
23 | struct equal_to_possible_exception : std::equal_to<int> | |
24 | { | |
25 | equal_to_possible_exception(equal_to_possible_exception const&) {} | |
26 | }; | |
27 | ||
28 | // Test that the move constructor does actually move without throwing | |
29 | // an exception when it claims to. | |
30 | ||
31 | struct test_exception | |
32 | { | |
33 | }; | |
34 | ||
35 | bool throwing_test_exception = false; | |
36 | void test_throw(char const* name) | |
37 | { | |
38 | if (throwing_test_exception) { | |
39 | BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Throw exception in: " << name | |
40 | << std::endl; | |
41 | throw test_exception(); | |
42 | } | |
43 | } | |
7c673cae | 44 | |
b32b8144 FG |
45 | class hash_nothrow_move : boost::hash<int> |
46 | { | |
47 | BOOST_COPYABLE_AND_MOVABLE(hash_nothrow_move) | |
7c673cae | 48 | |
b32b8144 | 49 | typedef boost::hash<int> base; |
7c673cae | 50 | |
b32b8144 FG |
51 | public: |
52 | hash_nothrow_move(BOOST_RV_REF(hash_nothrow_move)) BOOST_NOEXCEPT {} | |
7c673cae | 53 | |
b32b8144 FG |
54 | hash_nothrow_move() { test_throw("Constructor"); } |
55 | hash_nothrow_move(hash_nothrow_move const&) { test_throw("Copy"); } | |
56 | hash_nothrow_move& operator=(BOOST_COPY_ASSIGN_REF(hash_nothrow_move)) | |
57 | { | |
58 | test_throw("Assign"); | |
59 | return *this; | |
60 | } | |
61 | hash_nothrow_move& operator=(BOOST_RV_REF(hash_nothrow_move)) | |
62 | { | |
63 | test_throw("Move Assign"); | |
64 | return *this; | |
65 | } | |
66 | std::size_t operator()(int x) const | |
67 | { | |
68 | test_throw("Operator"); | |
69 | return static_cast<base const&>(*this)(x); | |
7c673cae | 70 | } |
b32b8144 | 71 | }; |
7c673cae | 72 | |
b32b8144 FG |
73 | class equal_to_nothrow_move : std::equal_to<int> |
74 | { | |
75 | BOOST_COPYABLE_AND_MOVABLE(equal_to_nothrow_move) | |
76 | ||
77 | typedef std::equal_to<int> base; | |
78 | ||
79 | public: | |
80 | equal_to_nothrow_move(BOOST_RV_REF(equal_to_nothrow_move)) BOOST_NOEXCEPT {} | |
81 | equal_to_nothrow_move() { test_throw("Constructor"); } | |
82 | equal_to_nothrow_move(equal_to_nothrow_move const&) { test_throw("Copy"); } | |
83 | equal_to_nothrow_move& operator=( | |
84 | BOOST_COPY_ASSIGN_REF(equal_to_nothrow_move)) | |
7c673cae | 85 | { |
b32b8144 FG |
86 | test_throw("Assign"); |
87 | return *this; | |
88 | } | |
89 | equal_to_nothrow_move& operator=(BOOST_RV_REF(equal_to_nothrow_move)) | |
7c673cae | 90 | { |
b32b8144 FG |
91 | test_throw("Move Assign"); |
92 | return *this; | |
93 | } | |
94 | std::size_t operator()(int x, int y) const | |
7c673cae | 95 | { |
b32b8144 FG |
96 | test_throw("Operator"); |
97 | return static_cast<base const&>(*this)(x, y); | |
98 | } | |
99 | }; | |
100 | ||
101 | bool have_is_nothrow_move = false; | |
102 | ||
103 | UNORDERED_AUTO_TEST (check_is_nothrow_move) { | |
104 | BOOST_TEST( | |
105 | !boost::is_nothrow_move_constructible<hash_possible_exception>::value); | |
106 | have_is_nothrow_move = | |
107 | boost::is_nothrow_move_constructible<hash_nothrow_move>::value; | |
108 | ||
109 | // Copied from boost::is_nothrow_move_constructible implementation | |
110 | // to make sure this does actually detect it when expected. | |
111 | // | |
112 | // The type trait is also available when BOOST_IS_NOTHROW_MOVE_CONSTRUCT | |
113 | // is defined (for some versions of Visual C++?) but detects 'throw()', | |
114 | // not noexcept. | |
115 | #if !defined(BOOST_NO_CXX11_NOEXCEPT) && !defined(BOOST_NO_SFINAE_EXPR) && \ | |
116 | !BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800) | |
117 | BOOST_TEST(have_is_nothrow_move); | |
7c673cae | 118 | #endif |
b32b8144 FG |
119 | } |
120 | ||
121 | UNORDERED_AUTO_TEST (test_noexcept) { | |
122 | if (have_is_nothrow_move) { | |
123 | BOOST_TEST((boost::is_nothrow_move_constructible< | |
124 | boost::unordered_set<int> >::value)); | |
125 | BOOST_TEST((boost::is_nothrow_move_constructible< | |
126 | boost::unordered_multiset<int> >::value)); | |
127 | BOOST_TEST((boost::is_nothrow_move_constructible< | |
128 | boost::unordered_map<int, int> >::value)); | |
129 | BOOST_TEST((boost::is_nothrow_move_constructible< | |
130 | boost::unordered_multimap<int, int> >::value)); | |
7c673cae FG |
131 | } |
132 | ||
b32b8144 FG |
133 | BOOST_TEST((!boost::is_nothrow_move_constructible< |
134 | boost::unordered_set<int, hash_possible_exception> >::value)); | |
135 | BOOST_TEST( | |
136 | (!boost::is_nothrow_move_constructible<boost::unordered_multiset<int, | |
137 | boost::hash<int>, equal_to_possible_exception> >::value)); | |
138 | } | |
7c673cae | 139 | |
b32b8144 FG |
140 | UNORDERED_AUTO_TEST (test_no_throw_when_noexcept) { |
141 | typedef boost::unordered_set<int, hash_nothrow_move, equal_to_nothrow_move> | |
142 | throwing_set; | |
7c673cae | 143 | |
b32b8144 FG |
144 | if (have_is_nothrow_move) { |
145 | BOOST_TEST(boost::is_nothrow_move_constructible<throwing_set>::value); | |
7c673cae | 146 | |
b32b8144 | 147 | throwing_test_exception = false; |
7c673cae | 148 | |
b32b8144 FG |
149 | throwing_set x1; |
150 | x1.insert(10); | |
151 | x1.insert(50); | |
7c673cae | 152 | |
b32b8144 FG |
153 | try { |
154 | throwing_test_exception = true; | |
7c673cae | 155 | |
b32b8144 FG |
156 | throwing_set x2 = boost::move(x1); |
157 | BOOST_TEST(x2.size() == 2); | |
158 | BOOST_TEST(*x2.begin() == 10 || *x2.begin() == 50); | |
159 | } catch (test_exception) { | |
160 | BOOST_TEST(false); | |
161 | } | |
7c673cae | 162 | |
b32b8144 | 163 | throwing_test_exception = false; |
7c673cae | 164 | } |
b32b8144 | 165 | } |
7c673cae FG |
166 | } |
167 | ||
168 | RUN_TESTS() |