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 // UNSUPPORTED: c++03, c++11, c++14
10
11 // <memory>
12
13 // template <class ForwardIt, class Size>
14 // constexpr ForwardIt destroy_n(ForwardIt, Size s);
15
16 #include <memory>
17 #include <cassert>
18 #include <type_traits>
19
20 #include "test_macros.h"
21 #include "test_iterators.h"
22
23 struct Counted {
24 int* counter_;
CountedCounted25 TEST_CONSTEXPR Counted(int* counter) : counter_(counter) { ++*counter_; }
CountedCounted26 TEST_CONSTEXPR Counted(Counted const& other) : counter_(other.counter_) { ++*counter_; }
~CountedCounted27 TEST_CONSTEXPR_CXX20 ~Counted() { --*counter_; }
28 friend void operator&(Counted) = delete;
29 };
30
31 #if TEST_STD_VER > 17
test_arrays()32 constexpr bool test_arrays() {
33 {
34 using Array = Counted[3];
35 using Alloc = std::allocator<Array>;
36 int counter = 0;
37 Alloc alloc;
38 Array* pool = std::allocator_traits<Alloc>::allocate(alloc, 5);
39
40 for (Array* p = pool; p != pool + 5; ++p) {
41 Array& arr = *p;
42 for (int i = 0; i != 3; ++i) {
43 std::allocator_traits<Alloc>::construct(alloc, std::addressof(arr[i]), &counter);
44 }
45 }
46 assert(counter == 5 * 3);
47
48 Array* p = std::destroy_n(pool, 5);
49 ASSERT_SAME_TYPE(decltype(std::destroy_n(pool, 5)), Array*);
50 assert(p == pool + 5);
51 assert(counter == 0);
52
53 std::allocator_traits<Alloc>::deallocate(alloc, pool, 5);
54 }
55 {
56 using Array = Counted[3][2];
57 using Alloc = std::allocator<Array>;
58 int counter = 0;
59 Alloc alloc;
60 Array* pool = std::allocator_traits<Alloc>::allocate(alloc, 5);
61
62 for (Array* p = pool; p != pool + 5; ++p) {
63 Array& arr = *p;
64 for (int i = 0; i != 3; ++i) {
65 for (int j = 0; j != 2; ++j) {
66 std::allocator_traits<Alloc>::construct(alloc, std::addressof(arr[i][j]), &counter);
67 }
68 }
69 }
70 assert(counter == 5 * 3 * 2);
71
72 Array* p = std::destroy_n(pool, 5);
73 ASSERT_SAME_TYPE(decltype(std::destroy_n(pool, 5)), Array*);
74 assert(p == pool + 5);
75 assert(counter == 0);
76
77 std::allocator_traits<Alloc>::deallocate(alloc, pool, 5);
78 }
79
80 return true;
81 }
82 #endif
83
84 template <class It>
test()85 TEST_CONSTEXPR_CXX20 void test() {
86 using Alloc = std::allocator<Counted>;
87 int counter = 0;
88 Alloc alloc;
89 Counted* pool = std::allocator_traits<Alloc>::allocate(alloc, 5);
90
91 for (Counted* p = pool; p != pool + 5; ++p)
92 std::allocator_traits<Alloc>::construct(alloc, p, &counter);
93 assert(counter == 5);
94
95 It it = std::destroy_n(It(pool), 5);
96 ASSERT_SAME_TYPE(decltype(std::destroy_n(It(pool), 5)), It);
97 assert(it == It(pool + 5));
98 assert(counter == 0);
99
100 std::allocator_traits<Alloc>::deallocate(alloc, pool, 5);
101 }
102
tests()103 TEST_CONSTEXPR_CXX20 bool tests() {
104 test<Counted*>();
105 test<forward_iterator<Counted*>>();
106 return true;
107 }
108
main(int,char **)109 int main(int, char**) {
110 tests();
111 #if TEST_STD_VER > 17
112 test_arrays();
113 static_assert(tests());
114 // TODO: Until std::construct_at has support for arrays, it's impossible to test this
115 // in a constexpr context (see https://reviews.llvm.org/D114903).
116 // static_assert(test_arrays());
117 #endif
118 return 0;
119 }
120