1 | //===----------------------------------------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | |
10 | // <memory> |
11 | |
12 | // template <typename _Alloc> |
13 | // void __swap_allocator(_Alloc& __a1, _Alloc& __a2); |
14 | |
15 | #include <cassert> |
16 | #include <memory> |
17 | // Transitively includes `swap_allocator.h` (directly including it breaks the modules build). |
18 | #include <vector> |
19 | #include <utility> |
20 | |
21 | #include "test_macros.h" |
22 | |
23 | template <bool Propagate, bool Noexcept> |
24 | struct Alloc { |
25 | int i = 0; |
26 | Alloc() = default; |
27 | Alloc(int set_i) : i(set_i) {} |
28 | |
29 | using value_type = int; |
30 | using propagate_on_container_swap = std::integral_constant<bool, Propagate>; |
31 | |
32 | friend void swap(Alloc& a1, Alloc& a2) TEST_NOEXCEPT_COND(Noexcept) { |
33 | std::swap(a1.i, a2.i); |
34 | } |
35 | |
36 | }; |
37 | |
38 | using PropagatingAlloc = Alloc</*Propagate=*/true, /*Noexcept=*/true>; |
39 | static_assert(std::allocator_traits<PropagatingAlloc>::propagate_on_container_swap::value, "" ); |
40 | |
41 | using NonPropagatingAlloc = Alloc</*Propagate=*/false, /*Noexcept=*/true>; |
42 | static_assert(!std::allocator_traits<NonPropagatingAlloc>::propagate_on_container_swap::value, "" ); |
43 | |
44 | using NoexceptSwapAlloc = Alloc</*Propagate=*/true, /*Noexcept=*/true>; |
45 | using ThrowingSwapAlloc = Alloc</*Propagate=*/true, /*Noexcept=*/false>; |
46 | |
47 | int main(int, char**) { |
48 | { |
49 | PropagatingAlloc a1(1), a2(42); |
50 | std::__swap_allocator(a1, a2); |
51 | assert(a1.i == 42); |
52 | assert(a2.i == 1); |
53 | } |
54 | |
55 | { |
56 | NonPropagatingAlloc a1(1), a2(42); |
57 | std::__swap_allocator(a1, a2); |
58 | assert(a1.i == 1); |
59 | assert(a2.i == 42); |
60 | } |
61 | |
62 | #if TEST_STD_VER >= 11 |
63 | { |
64 | NoexceptSwapAlloc noexcept_alloc; |
65 | static_assert(noexcept(std::__swap_allocator(noexcept_alloc, noexcept_alloc)), "" ); |
66 | } |
67 | |
68 | #if TEST_STD_VER > 11 |
69 | { // From C++14, `__swap_allocator` is unconditionally noexcept. |
70 | ThrowingSwapAlloc throwing_alloc; |
71 | static_assert(noexcept(std::__swap_allocator(throwing_alloc, throwing_alloc)), "" ); |
72 | } |
73 | #else |
74 | { // Until C++14, `__swap_allocator` is only noexcept if the underlying `swap` function is `noexcept`. |
75 | ThrowingSwapAlloc throwing_alloc; |
76 | static_assert(!noexcept(std::__swap_allocator(throwing_alloc, throwing_alloc)), "" ); |
77 | } |
78 | #endif // TEST_STD_VER > 11 |
79 | #endif // TEST_STD_VER >= 11 |
80 | |
81 | return 0; |
82 | } |
83 | |