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
23template <bool Propagate, bool Noexcept>
24struct 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
38using PropagatingAlloc = Alloc</*Propagate=*/true, /*Noexcept=*/true>;
39static_assert(std::allocator_traits<PropagatingAlloc>::propagate_on_container_swap::value, "");
40
41using NonPropagatingAlloc = Alloc</*Propagate=*/false, /*Noexcept=*/true>;
42static_assert(!std::allocator_traits<NonPropagatingAlloc>::propagate_on_container_swap::value, "");
43
44using NoexceptSwapAlloc = Alloc</*Propagate=*/true, /*Noexcept=*/true>;
45using ThrowingSwapAlloc = Alloc</*Propagate=*/true, /*Noexcept=*/false>;
46
47int 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

source code of libcxx/test/libcxx/memory/swap_allocator.pass.cpp