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
23struct Counted {
24 int* counter_;
25 TEST_CONSTEXPR Counted(int* counter) : counter_(counter) { ++*counter_; }
26 TEST_CONSTEXPR Counted(Counted const& other) : counter_(other.counter_) { ++*counter_; }
27 TEST_CONSTEXPR_CXX20 ~Counted() { --*counter_; }
28 friend void operator&(Counted) = delete;
29};
30
31#if TEST_STD_VER > 17
32constexpr 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
84template <class It>
85TEST_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(a&: alloc, n: 5);
90
91 for (Counted* p = pool; p != pool + 5; ++p)
92 std::allocator_traits<Alloc>::construct(a&: alloc, p: p, args: &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(a&: alloc, p: pool, n: 5);
101}
102
103TEST_CONSTEXPR_CXX20 bool tests() {
104 test<Counted*>();
105 test<forward_iterator<Counted*>>();
106 return true;
107}
108
109int 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

source code of libcxx/test/std/utilities/memory/specialized.algorithms/specialized.destroy/destroy_n.pass.cpp