diff options
Diffstat (limited to 'libcxx/test')
14 files changed, 1048 insertions, 12 deletions
diff --git a/libcxx/test/std/containers/associative/map/map.special/swap_noexcept.pass.cpp b/libcxx/test/std/containers/associative/map/map.special/swap_noexcept.pass.cpp index c238ed2c4b6..4598e9945d4 100644 --- a/libcxx/test/std/containers/associative/map/map.special/swap_noexcept.pass.cpp +++ b/libcxx/test/std/containers/associative/map/map.special/swap_noexcept.pass.cpp @@ -12,6 +12,10 @@ // void swap(map& c) // noexcept(!allocator_type::propagate_on_container_swap::value || // __is_nothrow_swappable<allocator_type>::value); +// +// In C++17, the standard says that swap shall have: +// noexcept(allocator_traits<Allocator>::is_always_equal::value && +// noexcept(swap(declval<Compare&>(), declval<Compare&>()))); // This tests a conforming extension @@ -33,6 +37,60 @@ struct some_comp typedef std::true_type propagate_on_container_swap; }; +template <class T> +struct some_comp2 +{ + typedef T value_type; + + some_comp2() {} + some_comp2(const some_comp2&) {} + void deallocate(void*, unsigned) {} + typedef std::true_type propagate_on_container_swap; +}; + +#if TEST_STD_VER >= 14 +template <typename T> +void swap(some_comp2<T>&, some_comp2<T>&) noexcept {} +#endif + +template <class T> +struct some_alloc +{ + typedef T value_type; + + some_alloc() {} + some_alloc(const some_alloc&); + void deallocate(void*, unsigned) {} + + typedef std::true_type propagate_on_container_swap; +}; + +template <class T> +struct some_alloc2 +{ + typedef T value_type; + + some_alloc2() {} + some_alloc2(const some_alloc2&); + void deallocate(void*, unsigned) {} + + typedef std::false_type propagate_on_container_swap; + typedef std::true_type is_always_equal; +}; + +template <class T> +struct some_alloc3 +{ + typedef T value_type; + + some_alloc3() {} + some_alloc3(const some_alloc3&); + void deallocate(void*, unsigned) {} + + typedef std::false_type propagate_on_container_swap; + typedef std::false_type is_always_equal; +}; + int main() { #if __has_feature(cxx_noexcept) @@ -56,5 +114,35 @@ int main() C c1, c2; static_assert(!noexcept(swap(c1, c2)), ""); } + +#if TEST_STD_VER >= 14 + { // POCS allocator, throwable swap for comp + typedef std::map<MoveOnly, MoveOnly, some_comp <MoveOnly>, some_alloc <MoveOnly>> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // always equal allocator, throwable swap for comp + typedef std::map<MoveOnly, MoveOnly, some_comp <MoveOnly>, some_alloc2<MoveOnly>> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // POCS allocator, nothrow swap for comp + typedef std::map<MoveOnly, MoveOnly, some_comp2<MoveOnly>, some_alloc <MoveOnly>> C; + C c1, c2; + static_assert( noexcept(swap(c1, c2)), ""); + } + { // always equal allocator, nothrow swap for comp + typedef std::map<MoveOnly, MoveOnly, some_comp2<MoveOnly>, some_alloc2<MoveOnly>> C; + C c1, c2; + static_assert( noexcept(swap(c1, c2)), ""); + } + + { // NOT always equal allocator, nothrow swap for comp + typedef std::map<MoveOnly, MoveOnly, some_comp2<MoveOnly>, some_alloc3<MoveOnly>> C; + C c1, c2; + static_assert( noexcept(swap(c1, c2)), ""); + } +#endif + #endif } diff --git a/libcxx/test/std/containers/associative/multimap/multimap.special/swap_noexcept.pass.cpp b/libcxx/test/std/containers/associative/multimap/multimap.special/swap_noexcept.pass.cpp index 07882a42289..1013c62804b 100644 --- a/libcxx/test/std/containers/associative/multimap/multimap.special/swap_noexcept.pass.cpp +++ b/libcxx/test/std/containers/associative/multimap/multimap.special/swap_noexcept.pass.cpp @@ -12,6 +12,10 @@ // void swap(multimap& c) // noexcept(!allocator_type::propagate_on_container_swap::value || // __is_nothrow_swappable<allocator_type>::value); +// +// In C++17, the standard says that swap shall have: +// noexcept(allocator_traits<Allocator>::is_always_equal::value && +// noexcept(swap(declval<Compare&>(), declval<Compare&>()))); // This tests a conforming extension @@ -33,6 +37,60 @@ struct some_comp typedef std::true_type propagate_on_container_swap; }; +template <class T> +struct some_comp2 +{ + typedef T value_type; + + some_comp2() {} + some_comp2(const some_comp2&) {} + void deallocate(void*, unsigned) {} + typedef std::true_type propagate_on_container_swap; +}; + +#if TEST_STD_VER >= 14 +template <typename T> +void swap(some_comp2<T>&, some_comp2<T>&) noexcept {} +#endif + +template <class T> +struct some_alloc +{ + typedef T value_type; + + some_alloc() {} + some_alloc(const some_alloc&); + void deallocate(void*, unsigned) {} + + typedef std::true_type propagate_on_container_swap; +}; + +template <class T> +struct some_alloc2 +{ + typedef T value_type; + + some_alloc2() {} + some_alloc2(const some_alloc2&); + void deallocate(void*, unsigned) {} + + typedef std::false_type propagate_on_container_swap; + typedef std::true_type is_always_equal; +}; + +template <class T> +struct some_alloc3 +{ + typedef T value_type; + + some_alloc3() {} + some_alloc3(const some_alloc3&); + void deallocate(void*, unsigned) {} + + typedef std::false_type propagate_on_container_swap; + typedef std::false_type is_always_equal; +}; + int main() { #if __has_feature(cxx_noexcept) @@ -56,5 +114,35 @@ int main() C c1, c2; static_assert(!noexcept(swap(c1, c2)), ""); } + +#if TEST_STD_VER >= 14 + { // POCS allocator, throwable swap for comp + typedef std::multimap<MoveOnly, MoveOnly, some_comp <MoveOnly>, some_alloc <MoveOnly>> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // always equal allocator, throwable swap for comp + typedef std::multimap<MoveOnly, MoveOnly, some_comp <MoveOnly>, some_alloc2<MoveOnly>> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // POCS allocator, nothrow swap for comp + typedef std::multimap<MoveOnly, MoveOnly, some_comp2<MoveOnly>, some_alloc <MoveOnly>> C; + C c1, c2; + static_assert( noexcept(swap(c1, c2)), ""); + } + { // always equal allocator, nothrow swap for comp + typedef std::multimap<MoveOnly, MoveOnly, some_comp2<MoveOnly>, some_alloc2<MoveOnly>> C; + C c1, c2; + static_assert( noexcept(swap(c1, c2)), ""); + } + + { // NOT always equal allocator, nothrow swap for comp + typedef std::map<MoveOnly, MoveOnly, some_comp2<MoveOnly>, some_alloc3<MoveOnly>> C; + C c1, c2; + static_assert( noexcept(swap(c1, c2)), ""); + } +#endif + #endif } diff --git a/libcxx/test/std/containers/associative/multiset/multiset.special/swap_noexcept.pass.cpp b/libcxx/test/std/containers/associative/multiset/multiset.special/swap_noexcept.pass.cpp index cd5be791cda..8e2c67c9b5e 100644 --- a/libcxx/test/std/containers/associative/multiset/multiset.special/swap_noexcept.pass.cpp +++ b/libcxx/test/std/containers/associative/multiset/multiset.special/swap_noexcept.pass.cpp @@ -12,6 +12,10 @@ // void swap(multiset& c) // noexcept(!allocator_type::propagate_on_container_swap::value || // __is_nothrow_swappable<allocator_type>::value); +// +// In C++17, the standard says that swap shall have: +// noexcept(allocator_traits<Allocator>::is_always_equal::value && +// noexcept(swap(declval<Compare&>(), declval<Compare&>()))); // This tests a conforming extension @@ -33,6 +37,60 @@ struct some_comp typedef std::true_type propagate_on_container_swap; }; +template <class T> +struct some_comp2 +{ + typedef T value_type; + + some_comp2() {} + some_comp2(const some_comp2&) {} + void deallocate(void*, unsigned) {} + typedef std::true_type propagate_on_container_swap; +}; + +#if TEST_STD_VER >= 14 +template <typename T> +void swap(some_comp2<T>&, some_comp2<T>&) noexcept {} +#endif + +template <class T> +struct some_alloc +{ + typedef T value_type; + + some_alloc() {} + some_alloc(const some_alloc&); + void deallocate(void*, unsigned) {} + + typedef std::true_type propagate_on_container_swap; +}; + +template <class T> +struct some_alloc2 +{ + typedef T value_type; + + some_alloc2() {} + some_alloc2(const some_alloc2&); + void deallocate(void*, unsigned) {} + + typedef std::false_type propagate_on_container_swap; + typedef std::true_type is_always_equal; +}; + +template <class T> +struct some_alloc3 +{ + typedef T value_type; + + some_alloc3() {} + some_alloc3(const some_alloc3&); + void deallocate(void*, unsigned) {} + + typedef std::false_type propagate_on_container_swap; + typedef std::false_type is_always_equal; +}; + int main() { #if __has_feature(cxx_noexcept) @@ -56,5 +114,35 @@ int main() C c1, c2; static_assert(!noexcept(swap(c1, c2)), ""); } + +#if TEST_STD_VER >= 14 + { // POCS allocator, throwable swap for comp + typedef std::multiset<MoveOnly, some_comp <MoveOnly>, some_alloc <MoveOnly>> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // always equal allocator, throwable swap for comp + typedef std::multiset<MoveOnly, some_comp <MoveOnly>, some_alloc2<MoveOnly>> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // POCS allocator, nothrow swap for comp + typedef std::multiset<MoveOnly, some_comp2<MoveOnly>, some_alloc <MoveOnly>> C; + C c1, c2; + static_assert( noexcept(swap(c1, c2)), ""); + } + { // always equal allocator, nothrow swap for comp + typedef std::multiset<MoveOnly, some_comp2<MoveOnly>, some_alloc2<MoveOnly>> C; + C c1, c2; + static_assert( noexcept(swap(c1, c2)), ""); + } + + { // NOT always equal allocator, nothrow swap for comp + typedef std::multiset<MoveOnly, some_comp2<MoveOnly>, some_alloc3<MoveOnly>> C; + C c1, c2; + static_assert( noexcept(swap(c1, c2)), ""); + } +#endif + #endif } diff --git a/libcxx/test/std/containers/associative/set/set.special/swap_noexcept.pass.cpp b/libcxx/test/std/containers/associative/set/set.special/swap_noexcept.pass.cpp index a478b254908..3ec69761275 100644 --- a/libcxx/test/std/containers/associative/set/set.special/swap_noexcept.pass.cpp +++ b/libcxx/test/std/containers/associative/set/set.special/swap_noexcept.pass.cpp @@ -12,6 +12,10 @@ // void swap(set& c) // noexcept(!allocator_type::propagate_on_container_swap::value || // __is_nothrow_swappable<allocator_type>::value); +// +// In C++17, the standard says that swap shall have: +// noexcept(allocator_traits<Allocator>::is_always_equal::value && +// noexcept(swap(declval<Compare&>(), declval<Compare&>()))); // This tests a conforming extension @@ -33,6 +37,60 @@ struct some_comp typedef std::true_type propagate_on_container_swap; }; +template <class T> +struct some_comp2 +{ + typedef T value_type; + + some_comp2() {} + some_comp2(const some_comp2&) {} + void deallocate(void*, unsigned) {} + typedef std::true_type propagate_on_container_swap; +}; + +#if TEST_STD_VER >= 14 +template <typename T> +void swap(some_comp2<T>&, some_comp2<T>&) noexcept {} +#endif + +template <class T> +struct some_alloc +{ + typedef T value_type; + + some_alloc() {} + some_alloc(const some_alloc&); + void deallocate(void*, unsigned) {} + + typedef std::true_type propagate_on_container_swap; +}; + +template <class T> +struct some_alloc2 +{ + typedef T value_type; + + some_alloc2() {} + some_alloc2(const some_alloc2&); + void deallocate(void*, unsigned) {} + + typedef std::false_type propagate_on_container_swap; + typedef std::true_type is_always_equal; +}; + +template <class T> +struct some_alloc3 +{ + typedef T value_type; + + some_alloc3() {} + some_alloc3(const some_alloc3&); + void deallocate(void*, unsigned) {} + + typedef std::false_type propagate_on_container_swap; + typedef std::false_type is_always_equal; +}; + int main() { #if __has_feature(cxx_noexcept) @@ -56,5 +114,35 @@ int main() C c1, c2; static_assert(!noexcept(swap(c1, c2)), ""); } + +#if TEST_STD_VER >= 14 + { // POCS allocator, throwable swap for comp + typedef std::set<MoveOnly, some_comp <MoveOnly>, some_alloc <MoveOnly>> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // always equal allocator, throwable swap for comp + typedef std::set<MoveOnly, some_comp <MoveOnly>, some_alloc2<MoveOnly>> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // POCS allocator, nothrow swap for comp + typedef std::set<MoveOnly, some_comp2<MoveOnly>, some_alloc <MoveOnly>> C; + C c1, c2; + static_assert( noexcept(swap(c1, c2)), ""); + } + { // always equal allocator, nothrow swap for comp + typedef std::set<MoveOnly, some_comp2<MoveOnly>, some_alloc2<MoveOnly>> C; + C c1, c2; + static_assert( noexcept(swap(c1, c2)), ""); + } + + { // NOT always equal allocator, nothrow swap for comp + typedef std::set<MoveOnly, some_comp2<MoveOnly>, some_alloc3<MoveOnly>> C; + C c1, c2; + static_assert( noexcept(swap(c1, c2)), ""); + } +#endif + #endif } diff --git a/libcxx/test/std/containers/sequences/deque/deque.special/swap_noexcept.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.special/swap_noexcept.pass.cpp index 3c94eb04bff..83bcac8997e 100644 --- a/libcxx/test/std/containers/sequences/deque/deque.special/swap_noexcept.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.special/swap_noexcept.pass.cpp @@ -12,6 +12,9 @@ // void swap(deque& c) // noexcept(!allocator_type::propagate_on_container_swap::value || // __is_nothrow_swappable<allocator_type>::value); +// +// In C++17, the standard says that swap shall have: +// noexcept(allocator_traits<Allocator>::is_always_equal::value); // This tests a conforming extension @@ -33,6 +36,19 @@ struct some_alloc typedef std::true_type propagate_on_container_swap; }; +template <class T> +struct some_alloc2 +{ + typedef T value_type; + + some_alloc2() {} + some_alloc2(const some_alloc2&); + void deallocate(void*, unsigned) {} + + typedef std::false_type propagate_on_container_swap; + typedef std::true_type is_always_equal; +}; + int main() { #if __has_feature(cxx_noexcept) @@ -54,7 +70,21 @@ int main() { typedef std::deque<MoveOnly, some_alloc<MoveOnly>> C; C c1, c2; +#if TEST_STD_VER >= 14 + // In c++14, if POCS is set, swapping the allocator is required not to throw + static_assert( noexcept(swap(c1, c2)), ""); +#else static_assert(!noexcept(swap(c1, c2)), ""); +#endif } +#if TEST_STD_VER >= 14 + { + typedef std::deque<MoveOnly, some_alloc2<MoveOnly>> C; + C c1, c2; + // if the allocators are always equal, then the swap can be noexcept + static_assert( noexcept(swap(c1, c2)), ""); + } +#endif + #endif } diff --git a/libcxx/test/std/containers/sequences/forwardlist/forwardlist.spec/swap_noexcept.pass.cpp b/libcxx/test/std/containers/sequences/forwardlist/forwardlist.spec/swap_noexcept.pass.cpp index e36ba5bddf9..cbe8142eeb4 100644 --- a/libcxx/test/std/containers/sequences/forwardlist/forwardlist.spec/swap_noexcept.pass.cpp +++ b/libcxx/test/std/containers/sequences/forwardlist/forwardlist.spec/swap_noexcept.pass.cpp @@ -12,6 +12,9 @@ // void swap(forward_list& c) // noexcept(!allocator_type::propagate_on_container_swap::value || // __is_nothrow_swappable<allocator_type>::value); +// +// In C++17, the standard says that swap shall have: +// noexcept(is_always_equal<allocator_type>::value); // This tests a conforming extension @@ -33,6 +36,19 @@ struct some_alloc typedef std::true_type propagate_on_container_swap; }; +template <class T> +struct some_alloc2 +{ + typedef T value_type; + + some_alloc2() {} + some_alloc2(const some_alloc2&); + void deallocate(void*, unsigned) {} + + typedef std::false_type propagate_on_container_swap; + typedef std::true_type is_always_equal; +}; + int main() { #if __has_feature(cxx_noexcept) @@ -54,7 +70,21 @@ int main() { typedef std::forward_list<MoveOnly, some_alloc<MoveOnly>> C; C c1, c2; +#if TEST_STD_VER >= 14 + // In c++14, if POCS is set, swapping the allocator is required not to throw + static_assert( noexcept(swap(c1, c2)), ""); +#else static_assert(!noexcept(swap(c1, c2)), ""); +#endif } +#if TEST_STD_VER >= 14 + { + typedef std::forward_list<MoveOnly, some_alloc2<MoveOnly>> C; + C c1, c2; + // if the allocators are always equal, then the swap can be noexcept + static_assert( noexcept(swap(c1, c2)), ""); + } +#endif + #endif } diff --git a/libcxx/test/std/containers/sequences/list/list.special/swap_noexcept.pass.cpp b/libcxx/test/std/containers/sequences/list/list.special/swap_noexcept.pass.cpp index 54ae359c20b..9c83ad58fed 100644 --- a/libcxx/test/std/containers/sequences/list/list.special/swap_noexcept.pass.cpp +++ b/libcxx/test/std/containers/sequences/list/list.special/swap_noexcept.pass.cpp @@ -12,6 +12,9 @@ // void swap(list& c) // noexcept(!allocator_type::propagate_on_container_swap::value || // __is_nothrow_swappable<allocator_type>::value); +// +// In C++17, the standard says that swap shall have: +// noexcept(allocator_traits<Allocator>::is_always_equal::value); // This tests a conforming extension @@ -33,6 +36,19 @@ struct some_alloc typedef std::true_type propagate_on_container_swap; }; +template <class T> +struct some_alloc2 +{ + typedef T value_type; + + some_alloc2() {} + some_alloc2(const some_alloc2&); + void deallocate(void*, unsigned) {} + + typedef std::false_type propagate_on_container_swap; + typedef std::true_type is_always_equal; +}; + int main() { #if __has_feature(cxx_noexcept) @@ -54,7 +70,21 @@ int main() { typedef std::list<MoveOnly, some_alloc<MoveOnly>> C; C c1, c2; +#if TEST_STD_VER >= 14 + // In c++14, if POCS is set, swapping the allocator is required not to throw + static_assert( noexcept(swap(c1, c2)), ""); +#else static_assert(!noexcept(swap(c1, c2)), ""); +#endif } +#if TEST_STD_VER >= 14 + { + typedef std::list<MoveOnly, some_alloc2<MoveOnly>> C; + C c1, c2; + // if the allocators are always equal, then the swap can be noexcept + static_assert( noexcept(swap(c1, c2)), ""); + } +#endif + #endif } diff --git a/libcxx/test/std/containers/sequences/vector.bool/swap_noexcept.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/swap_noexcept.pass.cpp index bcaf161119f..6f36473fa98 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/swap_noexcept.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/swap_noexcept.pass.cpp @@ -12,6 +12,10 @@ // void swap(vector& c) // noexcept(!allocator_type::propagate_on_container_swap::value || // __is_nothrow_swappable<allocator_type>::value); +// +// In C++17, the standard says that swap shall have: +// noexcept(allocator_traits<Allocator>::propagate_on_container_swap::value || +// allocator_traits<Allocator>::is_always_equal::value); // This tests a conforming extension @@ -32,6 +36,19 @@ struct some_alloc typedef std::true_type propagate_on_container_swap; }; +template <class T> +struct some_alloc2 +{ + typedef T value_type; + + some_alloc2() {} + some_alloc2(const some_alloc2&); + void deallocate(void*, unsigned) {} + + typedef std::false_type propagate_on_container_swap; + typedef std::true_type is_always_equal; +}; + int main() { #if __has_feature(cxx_noexcept) @@ -53,7 +70,21 @@ int main() { typedef std::vector<bool, some_alloc<bool>> C; C c1, c2; +#if TEST_STD_VER >= 14 + // In c++14, if POCS is set, swapping the allocator is required not to throw + static_assert( noexcept(swap(c1, c2)), ""); +#else static_assert(!noexcept(swap(c1, c2)), ""); +#endif } +#if TEST_STD_VER >= 14 + { + typedef std::vector<bool, some_alloc2<bool>> C; + C c1, c2; + // if the allocators are always equal, then the swap can be noexcept + static_assert( noexcept(swap(c1, c2)), ""); + } +#endif + #endif } diff --git a/libcxx/test/std/containers/sequences/vector/vector.special/swap_noexcept.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.special/swap_noexcept.pass.cpp index 92d87568fc8..1d00ff38748 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.special/swap_noexcept.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.special/swap_noexcept.pass.cpp @@ -12,6 +12,10 @@ // void swap(vector& c) // noexcept(!allocator_type::propagate_on_container_swap::value || // __is_nothrow_swappable<allocator_type>::value); +// +// In C++17, the standard says that swap shall have: +// noexcept(allocator_traits<Allocator>::propagate_on_container_swap::value || +// allocator_traits<Allocator>::is_always_equal::value); // This tests a conforming extension @@ -33,6 +37,19 @@ struct some_alloc typedef std::true_type propagate_on_container_swap; }; +template <class T> +struct some_alloc2 +{ + typedef T value_type; + + some_alloc2() {} + some_alloc2(const some_alloc2&); + void deallocate(void*, unsigned) {} + + typedef std::false_type propagate_on_container_swap; + typedef std::true_type is_always_equal; +}; + int main() { #if __has_feature(cxx_noexcept) @@ -54,7 +71,21 @@ int main() { typedef std::vector<MoveOnly, some_alloc<MoveOnly>> C; C c1, c2; +#if TEST_STD_VER >= 14 + // In c++14, if POCS is set, swapping the allocator is required not to throw + static_assert( noexcept(swap(c1, c2)), ""); +#else static_assert(!noexcept(swap(c1, c2)), ""); +#endif } +#if TEST_STD_VER >= 14 + { + typedef std::vector<MoveOnly, some_alloc2<MoveOnly>> C; + C c1, c2; + // if the allocators are always equal, then the swap can be noexcept + static_assert( noexcept(swap(c1, c2)), ""); + } +#endif + #endif } diff --git a/libcxx/test/std/containers/unord/unord.map/unord.map.swap/swap_noexcept.pass.cpp b/libcxx/test/std/containers/unord/unord.map/unord.map.swap/swap_noexcept.pass.cpp index a986882eae3..1056c231f0d 100644 --- a/libcxx/test/std/containers/unord/unord.map/unord.map.swap/swap_noexcept.pass.cpp +++ b/libcxx/test/std/containers/unord/unord.map/unord.map.swap/swap_noexcept.pass.cpp @@ -10,8 +10,16 @@ // <unordered_map> // void swap(unordered_map& c) -// noexcept(!allocator_type::propagate_on_container_swap::value || -// __is_nothrow_swappable<allocator_type>::value); +// noexcept( +// (!allocator_type::propagate_on_container_swap::value || +// __is_nothrow_swappable<allocator_type>::value) && +// __is_nothrow_swappable<hasher>::value && +// __is_nothrow_swappable<key_equal>::value); +// +// In C++17, the standard says that swap shall have: +// noexcept(allocator_traits<Allocator>::is_always_equal::value && +// noexcept(swap(declval<Hash&>(), declval<Hash&>())) && +// noexcept(swap(declval<Pred&>(), declval<Pred&>()))); // This tests a conforming extension @@ -31,6 +39,22 @@ struct some_comp }; template <class T> +struct some_comp2 +{ + typedef T value_type; + + some_comp2() {} + some_comp2(const some_comp2&) {} + void deallocate(void*, unsigned) {} + typedef std::true_type propagate_on_container_swap; +}; + +#if TEST_STD_VER >= 14 +template <typename T> +void swap(some_comp2<T>&, some_comp2<T>&) noexcept {} +#endif + +template <class T> struct some_hash { typedef T value_type; @@ -38,9 +62,62 @@ struct some_hash some_hash(const some_hash&); }; +template <class T> +struct some_hash2 +{ + typedef T value_type; + some_hash2() {} + some_hash2(const some_hash2&); +}; + +#if TEST_STD_VER >= 14 +template <typename T> +void swap(some_hash2<T>&, some_hash2<T>&) noexcept {} +#endif + +template <class T> +struct some_alloc +{ + typedef T value_type; + + some_alloc() {} + some_alloc(const some_alloc&); + void deallocate(void*, unsigned) {} + + typedef std::true_type propagate_on_container_swap; +}; + +template <class T> +struct some_alloc2 +{ + typedef T value_type; + + some_alloc2() {} + some_alloc2(const some_alloc2&); + void deallocate(void*, unsigned) {} + + typedef std::false_type propagate_on_container_swap; + typedef std::true_type is_always_equal; +}; + +template <class T> +struct some_alloc3 +{ + typedef T value_type; + + some_alloc3() {} + some_alloc3(const some_alloc3&); + void deallocate(void*, unsigned) {} + + typedef std::false_type propagate_on_container_swap; + typedef std::false_type is_always_equal; +}; + + int main() { #if __has_feature(cxx_noexcept) + typedef std::pair<const MoveOnly, MoveOnly> MapType; { typedef std::unordered_map<MoveOnly, MoveOnly> C; C c1, c2; @@ -48,13 +125,13 @@ int main() } { typedef std::unordered_map<MoveOnly, MoveOnly, std::hash<MoveOnly>, - std::equal_to<MoveOnly>, test_allocator<std::pair<const MoveOnly, MoveOnly>>> C; + std::equal_to<MoveOnly>, test_allocator<MapType>> C; C c1, c2; static_assert(noexcept(swap(c1, c2)), ""); } { typedef std::unordered_map<MoveOnly, MoveOnly, std::hash<MoveOnly>, - std::equal_to<MoveOnly>, other_allocator<std::pair<const MoveOnly, MoveOnly>>> C; + std::equal_to<MoveOnly>, other_allocator<MapType>> C; C c1, c2; static_assert(noexcept(swap(c1, c2)), ""); } @@ -69,5 +146,54 @@ int main() C c1, c2; static_assert(!noexcept(swap(c1, c2)), ""); } + +#if TEST_STD_VER >= 14 + { // POCS allocator, throwable swap for hash, throwable swap for comp + typedef std::unordered_map<MoveOnly, MoveOnly, some_hash<MoveOnly>, some_comp <MoveOnly>, some_alloc <MapType>> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // always equal allocator, throwable swap for hash, throwable swap for comp + typedef std::unordered_map<MoveOnly, MoveOnly, some_hash<MoveOnly>, some_comp <MoveOnly>, some_alloc2<MapType>> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // POCS allocator, throwable swap for hash, nothrow swap for comp + typedef std::unordered_map<MoveOnly, MoveOnly, some_hash<MoveOnly>, some_comp2<MoveOnly>, some_alloc <MapType>> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // always equal allocator, throwable swap for hash, nothrow swap for comp + typedef std::unordered_map<MoveOnly, MoveOnly, some_hash<MoveOnly>, some_comp2<MoveOnly>, some_alloc2<MapType>> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // POCS allocator, nothrow swap for hash, throwable swap for comp + typedef std::unordered_map<MoveOnly, MoveOnly, some_hash2<MoveOnly>, some_comp <MoveOnly>, some_alloc <MapType>> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // always equal allocator, nothrow swap for hash, throwable swap for comp + typedef std::unordered_map<MoveOnly, MoveOnly, some_hash2<MoveOnly>, some_comp <MoveOnly>, some_alloc2<MapType>> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // POCS allocator, nothrow swap for hash, nothrow swap for comp + typedef std::unordered_map<MoveOnly, MoveOnly, some_hash2<MoveOnly>, some_comp2<MoveOnly>, some_alloc <MapType>> C; + C c1, c2; + static_assert( noexcept(swap(c1, c2)), ""); + } + { // always equal allocator, nothrow swap for hash, nothrow swap for comp + typedef std::unordered_map<MoveOnly, MoveOnly, some_hash2<MoveOnly>, some_comp2<MoveOnly>, some_alloc2<MapType>> C; + C c1, c2; + static_assert( noexcept(swap(c1, c2)), ""); + } + + { // NOT always equal allocator, nothrow swap for hash, nothrow swap for comp + typedef std::unordered_map<MoveOnly, MoveOnly, some_hash2<MoveOnly>, some_comp2<MoveOnly>, some_alloc3<MapType>> C; + C c1, c2; + static_assert( noexcept(swap(c1, c2)), ""); + } +#endif #endif } diff --git a/libcxx/test/std/containers/unord/unord.multimap/unord.multimap.swap/swap_noexcept.pass.cpp b/libcxx/test/std/containers/unord/unord.multimap/unord.multimap.swap/swap_noexcept.pass.cpp index c690bb61bb3..37c8119060b 100644 --- a/libcxx/test/std/containers/unord/unord.multimap/unord.multimap.swap/swap_noexcept.pass.cpp +++ b/libcxx/test/std/containers/unord/unord.multimap/unord.multimap.swap/swap_noexcept.pass.cpp @@ -10,8 +10,16 @@ // <unordered_map> // void swap(unordered_multimap& c) -// noexcept(!allocator_type::propagate_on_container_swap::value || -// __is_nothrow_swappable<allocator_type>::value); +// noexcept( +// (!allocator_type::propagate_on_container_swap::value || +// __is_nothrow_swappable<allocator_type>::value) && +// __is_nothrow_swappable<hasher>::value && +// __is_nothrow_swappable<key_equal>::value); +// +// In C++17, the standard says that swap shall have: +// noexcept(allocator_traits<allocator_type>::is_always_equal::value && +// __is_nothrow_swappable<hasher>::value && +// __is_nothrow_swappable<key_equal>::value); // This tests a conforming extension @@ -31,6 +39,22 @@ struct some_comp }; template <class T> +struct some_comp2 +{ + typedef T value_type; + + some_comp2() {} + some_comp2(const some_comp2&) {} + void deallocate(void*, unsigned) {} + typedef std::true_type propagate_on_container_swap; +}; + +#if TEST_STD_VER >= 14 +template <typename T> +void swap(some_comp2<T>&, some_comp2<T>&) noexcept {} +#endif + +template <class T> struct some_hash { typedef T value_type; @@ -38,9 +62,61 @@ struct some_hash some_hash(const some_hash&); }; +template <class T> +struct some_hash2 +{ + typedef T value_type; + some_hash2() {} + some_hash2(const some_hash2&); +}; + +#if TEST_STD_VER >= 14 +template <typename T> +void swap(some_hash2<T>&, some_hash2<T>&) noexcept {} +#endif + +template <class T> +struct some_alloc +{ + typedef T value_type; + + some_alloc() {} + some_alloc(const some_alloc&); + void deallocate(void*, unsigned) {} + + typedef std::true_type propagate_on_container_swap; +}; + +template <class T> +struct some_alloc2 +{ + typedef T value_type; + + some_alloc2() {} + some_alloc2(const some_alloc2&); + void deallocate(void*, unsigned) {} + + typedef std::false_type propagate_on_container_swap; + typedef std::true_type is_always_equal; +}; + +template <class T> +struct some_alloc3 +{ + typedef T value_type; + + some_alloc3() {} + some_alloc3(const some_alloc3&); + void deallocate(void*, unsigned) {} + + typedef std::false_type propagate_on_container_swap; + typedef std::false_type is_always_equal; +}; + int main() { #if __has_feature(cxx_noexcept) + typedef std::pair<const MoveOnly, MoveOnly> MapType; { typedef std::unordered_multimap<MoveOnly, MoveOnly> C; C c1, c2; @@ -48,13 +124,13 @@ int main() } { typedef std::unordered_multimap<MoveOnly, MoveOnly, std::hash<MoveOnly>, - std::equal_to<MoveOnly>, test_allocator<std::pair<const MoveOnly, MoveOnly>>> C; + std::equal_to<MoveOnly>, test_allocator<MapType>> C; C c1, c2; static_assert(noexcept(swap(c1, c2)), ""); } { typedef std::unordered_multimap<MoveOnly, MoveOnly, std::hash<MoveOnly>, - std::equal_to<MoveOnly>, other_allocator<std::pair<const MoveOnly, MoveOnly>>> C; + std::equal_to<MoveOnly>, other_allocator<MapType>> C; C c1, c2; static_assert(noexcept(swap(c1, c2)), ""); } @@ -69,5 +145,54 @@ int main() C c1, c2; static_assert(!noexcept(swap(c1, c2)), ""); } + +#if TEST_STD_VER >= 14 + { // POCS allocator, throwable swap for hash, throwable swap for comp + typedef std::unordered_multimap<MoveOnly, MoveOnly, some_hash<MoveOnly>, some_comp <MoveOnly>, some_alloc <MapType>> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // always equal allocator, throwable swap for hash, throwable swap for comp + typedef std::unordered_multimap<MoveOnly, MoveOnly, some_hash<MoveOnly>, some_comp <MoveOnly>, some_alloc2<MapType>> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // POCS allocator, throwable swap for hash, nothrow swap for comp + typedef std::unordered_multimap<MoveOnly, MoveOnly, some_hash<MoveOnly>, some_comp2<MoveOnly>, some_alloc <MapType>> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // always equal allocator, throwable swap for hash, nothrow swap for comp + typedef std::unordered_multimap<MoveOnly, MoveOnly, some_hash<MoveOnly>, some_comp2<MoveOnly>, some_alloc2<MapType>> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // POCS allocator, nothrow swap for hash, throwable swap for comp + typedef std::unordered_multimap<MoveOnly, MoveOnly, some_hash2<MoveOnly>, some_comp <MoveOnly>, some_alloc <MapType>> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // always equal allocator, nothrow swap for hash, throwable swap for comp + typedef std::unordered_multimap<MoveOnly, MoveOnly, some_hash2<MoveOnly>, some_comp <MoveOnly>, some_alloc2<MapType>> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // POCS allocator, nothrow swap for hash, nothrow swap for comp + typedef std::unordered_multimap<MoveOnly, MoveOnly, some_hash2<MoveOnly>, some_comp2<MoveOnly>, some_alloc <MapType>> C; + C c1, c2; + static_assert( noexcept(swap(c1, c2)), ""); + } + { // always equal allocator, nothrow swap for hash, nothrow swap for comp + typedef std::unordered_multimap<MoveOnly, MoveOnly, some_hash2<MoveOnly>, some_comp2<MoveOnly>, some_alloc2<MapType>> C; + C c1, c2; + static_assert( noexcept(swap(c1, c2)), ""); + } + { // NOT always equal allocator, nothrow swap for hash, nothrow swap for comp + typedef std::unordered_multimap<MoveOnly, MoveOnly, some_hash2<MoveOnly>, some_comp2<MoveOnly>, some_alloc3<MapType>> C; + C c1, c2; + static_assert( noexcept(swap(c1, c2)), ""); + } +#endif + #endif } diff --git a/libcxx/test/std/containers/unord/unord.multiset/unord.multiset.swap/swap_noexcept.pass.cpp b/libcxx/test/std/containers/unord/unord.multiset/unord.multiset.swap/swap_noexcept.pass.cpp index 7dc653bca69..63642fcd7cc 100644 --- a/libcxx/test/std/containers/unord/unord.multiset/unord.multiset.swap/swap_noexcept.pass.cpp +++ b/libcxx/test/std/containers/unord/unord.multiset/unord.multiset.swap/swap_noexcept.pass.cpp @@ -10,8 +10,16 @@ // <unordered_set> // void swap(unordered_multiset& c) -// noexcept(!allocator_type::propagate_on_container_swap::value || -// __is_nothrow_swappable<allocator_type>::value); +// noexcept( +// (!allocator_type::propagate_on_container_swap::value || +// __is_nothrow_swappable<allocator_type>::value) && +// __is_nothrow_swappable<hasher>::value && +// __is_nothrow_swappable<key_equal>::value); +// +// In C++17, the standard says that swap shall have: +// noexcept(allocator_traits<Allocator>::is_always_equal::value && +// noexcept(swap(declval<Hash&>(), declval<Hash&>())) && +// noexcept(swap(declval<Pred&>(), declval<Pred&>()))); // This tests a conforming extension @@ -31,6 +39,22 @@ struct some_comp }; template <class T> +struct some_comp2 +{ + typedef T value_type; + + some_comp2() {} + some_comp2(const some_comp2&) {} + void deallocate(void*, unsigned) {} + typedef std::true_type propagate_on_container_swap; +}; + +#if TEST_STD_VER >= 14 +template <typename T> +void swap(some_comp2<T>&, some_comp2<T>&) noexcept {} +#endif + +template <class T> struct some_hash { typedef T value_type; @@ -38,6 +62,57 @@ struct some_hash some_hash(const some_hash&); }; +template <class T> +struct some_hash2 +{ + typedef T value_type; + some_hash2() {} + some_hash2(const some_hash2&); +}; + +#if TEST_STD_VER >= 14 +template <typename T> +void swap(some_hash2<T>&, some_hash2<T>&) noexcept {} +#endif + +template <class T> +struct some_alloc +{ + typedef T value_type; + + some_alloc() {} + some_alloc(const some_alloc&); + void deallocate(void*, unsigned) {} + + typedef std::true_type propagate_on_container_swap; +}; + +template <class T> +struct some_alloc2 +{ + typedef T value_type; + + some_alloc2() {} + some_alloc2(const some_alloc2&); + void deallocate(void*, unsigned) {} + + typedef std::false_type propagate_on_container_swap; + typedef std::true_type is_always_equal; +}; + +template <class T> +struct some_alloc3 +{ + typedef T value_type; + + some_alloc3() {} + some_alloc3(const some_alloc3&); + void deallocate(void*, unsigned) {} + + typedef std::false_type propagate_on_container_swap; + typedef std::false_type is_always_equal; +}; + int main() { #if __has_feature(cxx_noexcept) @@ -69,5 +144,55 @@ int main() C c1, c2; static_assert(!noexcept(swap(c1, c2)), ""); } + +#if TEST_STD_VER >= 14 + { // POCS allocator, throwable swap for hash, throwable swap for comp + typedef std::unordered_multiset<MoveOnly, some_hash<MoveOnly>, some_comp <MoveOnly>, some_alloc <MoveOnly>> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // always equal allocator, throwable swap for hash, throwable swap for comp + typedef std::unordered_multiset<MoveOnly, some_hash<MoveOnly>, some_comp <MoveOnly>, some_alloc2<MoveOnly>> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // POCS allocator, throwable swap for hash, nothrow swap for comp + typedef std::unordered_multiset<MoveOnly, some_hash<MoveOnly>, some_comp2<MoveOnly>, some_alloc <MoveOnly>> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // always equal allocator, throwable swap for hash, nothrow swap for comp + typedef std::unordered_multiset<MoveOnly, some_hash<MoveOnly>, some_comp2<MoveOnly>, some_alloc2<MoveOnly>> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // POCS allocator, nothrow swap for hash, throwable swap for comp + typedef std::unordered_multiset<MoveOnly, some_hash2<MoveOnly>, some_comp <MoveOnly>, some_alloc <MoveOnly>> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // always equal allocator, nothrow swap for hash, throwable swap for comp + typedef std::unordered_multiset<MoveOnly, some_hash2<MoveOnly>, some_comp <MoveOnly>, some_alloc2<MoveOnly>> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // POCS allocator, nothrow swap for hash, nothrow swap for comp + typedef std::unordered_multiset<MoveOnly, some_hash2<MoveOnly>, some_comp2<MoveOnly>, some_alloc <MoveOnly>> C; + C c1, c2; + static_assert( noexcept(swap(c1, c2)), ""); + } + { // always equal allocator, nothrow swap for hash, nothrow swap for comp + typedef std::unordered_multiset<MoveOnly, some_hash2<MoveOnly>, some_comp2<MoveOnly>, some_alloc2<MoveOnly>> C; + C c1, c2; + static_assert( noexcept(swap(c1, c2)), ""); + } + + { // NOT always equal allocator, nothrow swap for hash, nothrow swap for comp + typedef std::unordered_multiset<MoveOnly, some_hash2<MoveOnly>, some_comp2<MoveOnly>, some_alloc3<MoveOnly>> C; + C c1, c2; + static_assert( noexcept(swap(c1, c2)), ""); + } +#endif + #endif } diff --git a/libcxx/test/std/containers/unord/unord.set/unord.set.swap/swap_noexcept.pass.cpp b/libcxx/test/std/containers/unord/unord.set/unord.set.swap/swap_noexcept.pass.cpp index cba09231953..5d746407a80 100644 --- a/libcxx/test/std/containers/unord/unord.set/unord.set.swap/swap_noexcept.pass.cpp +++ b/libcxx/test/std/containers/unord/unord.set/unord.set.swap/swap_noexcept.pass.cpp @@ -10,8 +10,16 @@ // <unordered_set> // void swap(unordered_set& c) -// noexcept(!allocator_type::propagate_on_container_swap::value || -// __is_nothrow_swappable<allocator_type>::value); +// noexcept( +// (!allocator_type::propagate_on_container_swap::value || +// __is_nothrow_swappable<allocator_type>::value) && +// __is_nothrow_swappable<hasher>::value && +// __is_nothrow_swappable<key_equal>::value); +// +// In C++17, the standard says that swap shall have: +// noexcept(allocator_traits<Allocator>::is_always_equal::value && +// noexcept(swap(declval<Hash&>(), declval<Hash&>())) && +// noexcept(swap(declval<Pred&>(), declval<Pred&>()))); // This tests a conforming extension @@ -31,6 +39,22 @@ struct some_comp }; template <class T> +struct some_comp2 +{ + typedef T value_type; + + some_comp2() {} + some_comp2(const some_comp2&) {} + void deallocate(void*, unsigned) {} + typedef std::true_type propagate_on_container_swap; +}; + +#if TEST_STD_VER >= 14 +template <typename T> +void swap(some_comp2<T>&, some_comp2<T>&) noexcept {} +#endif + +template <class T> struct some_hash { typedef T value_type; @@ -38,6 +62,57 @@ struct some_hash some_hash(const some_hash&); }; +template <class T> +struct some_hash2 +{ + typedef T value_type; + some_hash2() {} + some_hash2(const some_hash2&); +}; + +#if TEST_STD_VER >= 14 +template <typename T> +void swap(some_hash2<T>&, some_hash2<T>&) noexcept {} +#endif + +template <class T> +struct some_alloc +{ + typedef T value_type; + + some_alloc() {} + some_alloc(const some_alloc&); + void deallocate(void*, unsigned) {} + + typedef std::true_type propagate_on_container_swap; +}; + +template <class T> +struct some_alloc2 +{ + typedef T value_type; + + some_alloc2() {} + some_alloc2(const some_alloc2&); + void deallocate(void*, unsigned) {} + + typedef std::false_type propagate_on_container_swap; + typedef std::true_type is_always_equal; +}; + +template <class T> +struct some_alloc3 +{ + typedef T value_type; + + some_alloc3() {} + some_alloc3(const some_alloc3&); + void deallocate(void*, unsigned) {} + + typedef std::false_type propagate_on_container_swap; + typedef std::false_type is_always_equal; +}; + int main() { #if __has_feature(cxx_noexcept) @@ -69,5 +144,55 @@ int main() C c1, c2; static_assert(!noexcept(swap(c1, c2)), ""); } + +#if TEST_STD_VER >= 14 + { // POCS allocator, throwable swap for hash, throwable swap for comp + typedef std::unordered_set<MoveOnly, some_hash<MoveOnly>, some_comp <MoveOnly>, some_alloc <MoveOnly>> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // always equal allocator, throwable swap for hash, throwable swap for comp + typedef std::unordered_set<MoveOnly, some_hash<MoveOnly>, some_comp <MoveOnly>, some_alloc2<MoveOnly>> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // POCS allocator, throwable swap for hash, nothrow swap for comp + typedef std::unordered_set<MoveOnly, some_hash<MoveOnly>, some_comp2<MoveOnly>, some_alloc <MoveOnly>> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // always equal allocator, throwable swap for hash, nothrow swap for comp + typedef std::unordered_set<MoveOnly, some_hash<MoveOnly>, some_comp2<MoveOnly>, some_alloc2<MoveOnly>> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // POCS allocator, nothrow swap for hash, throwable swap for comp + typedef std::unordered_set<MoveOnly, some_hash2<MoveOnly>, some_comp <MoveOnly>, some_alloc <MoveOnly>> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // always equal allocator, nothrow swap for hash, throwable swap for comp + typedef std::unordered_set<MoveOnly, some_hash2<MoveOnly>, some_comp <MoveOnly>, some_alloc2<MoveOnly>> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // POCS allocator, nothrow swap for hash, nothrow swap for comp + typedef std::unordered_set<MoveOnly, some_hash2<MoveOnly>, some_comp2<MoveOnly>, some_alloc <MoveOnly>> C; + C c1, c2; + static_assert( noexcept(swap(c1, c2)), ""); + } + { // always equal allocator, nothrow swap for hash, nothrow swap for comp + typedef std::unordered_set<MoveOnly, some_hash2<MoveOnly>, some_comp2<MoveOnly>, some_alloc2<MoveOnly>> C; + C c1, c2; + static_assert( noexcept(swap(c1, c2)), ""); + } + + { // NOT always equal allocator, nothrow swap for hash, nothrow swap for comp + typedef std::unordered_set<MoveOnly, some_hash2<MoveOnly>, some_comp2<MoveOnly>, some_alloc3<MoveOnly>> C; + C c1, c2; + static_assert( noexcept(swap(c1, c2)), ""); + } +#endif + #endif } diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string.special/swap_noexcept.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string.special/swap_noexcept.pass.cpp index 4d5d79693d0..cfe03655a8a 100644 --- a/libcxx/test/std/strings/basic.string/string.nonmembers/string.special/swap_noexcept.pass.cpp +++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string.special/swap_noexcept.pass.cpp @@ -12,6 +12,10 @@ // void swap(basic_string& c) // noexcept(!allocator_type::propagate_on_container_swap::value || // __is_nothrow_swappable<allocator_type>::value); +// +// In C++17, the standard says that swap shall have: +// noexcept(allocator_traits<Allocator>::propagate_on_container_swap::value || +// allocator_traits<Allocator>::is_always_equal::value); // This tests a conforming extension @@ -32,6 +36,19 @@ struct some_alloc typedef std::true_type propagate_on_container_swap; }; +template <class T> +struct some_alloc2 +{ + typedef T value_type; + + some_alloc2() {} + some_alloc2(const some_alloc2&); + void deallocate(void*, unsigned) {} + + typedef std::false_type propagate_on_container_swap; + typedef std::true_type is_always_equal; +}; + int main() { #if __has_feature(cxx_noexcept) @@ -48,7 +65,21 @@ int main() { typedef std::basic_string<char, std::char_traits<char>, some_alloc<char>> C; C c1, c2; +#if TEST_STD_VER >= 14 + // In c++14, if POCS is set, swapping the allocator is required not to throw + static_assert( noexcept(swap(c1, c2)), ""); +#else static_assert(!noexcept(swap(c1, c2)), ""); +#endif } +#if TEST_STD_VER >= 14 + { + typedef std::basic_string<char, std::char_traits<char>, some_alloc2<char>> C; + C c1, c2; + // if the allocators are always equal, then the swap can be noexcept + static_assert( noexcept(swap(c1, c2)), ""); + } +#endif + #endif } |

