swap_noexcept.pass.cpp revision c6c26a44def0e7811ffcd928b8eeafa1a6edd626
1//===----------------------------------------------------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10// UNSUPPORTED: c++98, c++03
11
12// <unordered_map>
13
14// void swap(unordered_map& c)
15//      noexcept(
16//          (!allocator_type::propagate_on_container_swap::value ||
17//           __is_nothrow_swappable<allocator_type>::value) &&
18//           __is_nothrow_swappable<hasher>::value &&
19//           __is_nothrow_swappable<key_equal>::value);
20//
21//  In C++17, the standard says that swap shall have:
22//     noexcept(allocator_traits<Allocator>::is_always_equal::value &&
23//               noexcept(swap(declval<Hash&>(), declval<Hash&>())) &&
24//               noexcept(swap(declval<Pred&>(), declval<Pred&>())));
25
26// This tests a conforming extension
27
28#include <unordered_map>
29#include <cassert>
30
31#include "test_macros.h"
32#include "MoveOnly.h"
33#include "test_allocator.h"
34
35template <class T>
36struct some_comp
37{
38    typedef T value_type;
39
40    some_comp() {}
41    some_comp(const some_comp&) {}
42};
43
44template <class T>
45struct some_comp2
46{
47    typedef T value_type;
48
49    some_comp2() {}
50    some_comp2(const some_comp2&) {}
51    void deallocate(void*, unsigned) {}
52    typedef std::true_type propagate_on_container_swap;
53};
54
55#if TEST_STD_VER >= 14
56template <typename T>
57void swap(some_comp2<T>&, some_comp2<T>&) noexcept {}
58#endif
59
60template <class T>
61struct some_hash
62{
63    typedef T value_type;
64    some_hash() {}
65    some_hash(const some_hash&);
66};
67
68template <class T>
69struct some_hash2
70{
71    typedef T value_type;
72    some_hash2() {}
73    some_hash2(const some_hash2&);
74};
75
76#if TEST_STD_VER >= 14
77template <typename T>
78void swap(some_hash2<T>&, some_hash2<T>&) noexcept {}
79#endif
80
81template <class T>
82struct some_alloc
83{
84    typedef T value_type;
85
86    some_alloc() {}
87    some_alloc(const some_alloc&);
88    void deallocate(void*, unsigned) {}
89
90    typedef std::true_type propagate_on_container_swap;
91};
92
93template <class T>
94struct some_alloc2
95{
96    typedef T value_type;
97
98    some_alloc2() {}
99    some_alloc2(const some_alloc2&);
100    void deallocate(void*, unsigned) {}
101
102    typedef std::false_type propagate_on_container_swap;
103    typedef std::true_type is_always_equal;
104};
105
106template <class T>
107struct some_alloc3
108{
109    typedef T value_type;
110
111    some_alloc3() {}
112    some_alloc3(const some_alloc3&);
113    void deallocate(void*, unsigned) {}
114
115    typedef std::false_type propagate_on_container_swap;
116    typedef std::false_type is_always_equal;
117};
118
119
120int main()
121{
122	typedef std::pair<const MoveOnly, MoveOnly> MapType;
123    {
124        typedef std::unordered_map<MoveOnly, MoveOnly> C;
125        C c1, c2;
126        static_assert(noexcept(swap(c1, c2)), "");
127    }
128    {
129        typedef std::unordered_map<MoveOnly, MoveOnly, std::hash<MoveOnly>,
130                           std::equal_to<MoveOnly>, test_allocator<MapType>> C;
131        C c1, c2;
132        static_assert(noexcept(swap(c1, c2)), "");
133    }
134    {
135        typedef std::unordered_map<MoveOnly, MoveOnly, std::hash<MoveOnly>,
136                          std::equal_to<MoveOnly>, other_allocator<MapType>> C;
137        C c1, c2;
138        static_assert(noexcept(swap(c1, c2)), "");
139    }
140    {
141        typedef std::unordered_map<MoveOnly, MoveOnly, some_hash<MoveOnly>> C;
142        C c1, c2;
143        static_assert(!noexcept(swap(c1, c2)), "");
144    }
145    {
146        typedef std::unordered_map<MoveOnly, MoveOnly, std::hash<MoveOnly>,
147                                                         some_comp<MoveOnly>> C;
148        C c1, c2;
149        static_assert(!noexcept(swap(c1, c2)), "");
150    }
151
152#if TEST_STD_VER >= 14
153    { // POCS allocator, throwable swap for hash, throwable swap for comp
154    typedef std::unordered_map<MoveOnly, MoveOnly, some_hash<MoveOnly>, some_comp <MoveOnly>, some_alloc <MapType>> C;
155    C c1, c2;
156    static_assert(!noexcept(swap(c1, c2)), "");
157    }
158    { // always equal allocator, throwable swap for hash, throwable swap for comp
159    typedef std::unordered_map<MoveOnly, MoveOnly, some_hash<MoveOnly>, some_comp <MoveOnly>, some_alloc2<MapType>> C;
160    C c1, c2;
161    static_assert(!noexcept(swap(c1, c2)), "");
162    }
163    { // POCS allocator, throwable swap for hash, nothrow swap for comp
164    typedef std::unordered_map<MoveOnly, MoveOnly, some_hash<MoveOnly>, some_comp2<MoveOnly>, some_alloc <MapType>> C;
165    C c1, c2;
166    static_assert(!noexcept(swap(c1, c2)), "");
167    }
168    { // always equal allocator, throwable swap for hash, nothrow swap for comp
169    typedef std::unordered_map<MoveOnly, MoveOnly, some_hash<MoveOnly>, some_comp2<MoveOnly>, some_alloc2<MapType>> C;
170    C c1, c2;
171    static_assert(!noexcept(swap(c1, c2)), "");
172    }
173    { // POCS allocator, nothrow swap for hash, throwable swap for comp
174    typedef std::unordered_map<MoveOnly, MoveOnly, some_hash2<MoveOnly>, some_comp <MoveOnly>, some_alloc <MapType>> C;
175    C c1, c2;
176    static_assert(!noexcept(swap(c1, c2)), "");
177    }
178    { // always equal allocator, nothrow swap for hash, throwable swap for comp
179    typedef std::unordered_map<MoveOnly, MoveOnly, some_hash2<MoveOnly>, some_comp <MoveOnly>, some_alloc2<MapType>> C;
180    C c1, c2;
181    static_assert(!noexcept(swap(c1, c2)), "");
182    }
183    { // POCS allocator, nothrow swap for hash, nothrow swap for comp
184    typedef std::unordered_map<MoveOnly, MoveOnly, some_hash2<MoveOnly>, some_comp2<MoveOnly>, some_alloc <MapType>> C;
185    C c1, c2;
186    static_assert( noexcept(swap(c1, c2)), "");
187    }
188    { // always equal allocator, nothrow swap for hash, nothrow swap for comp
189    typedef std::unordered_map<MoveOnly, MoveOnly, some_hash2<MoveOnly>, some_comp2<MoveOnly>, some_alloc2<MapType>> C;
190    C c1, c2;
191    static_assert( noexcept(swap(c1, c2)), "");
192    }
193
194    { // NOT always equal allocator, nothrow swap for hash, nothrow swap for comp
195    typedef std::unordered_map<MoveOnly, MoveOnly, some_hash2<MoveOnly>, some_comp2<MoveOnly>, some_alloc3<MapType>> C;
196    C c1, c2;
197    static_assert( noexcept(swap(c1, c2)), "");
198    }
199#endif
200}
201