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>
14// constexpr void destroy(ForwardIt, ForwardIt);
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 std::destroy(pool, pool + 5);
49 ASSERT_SAME_TYPE(decltype(std::destroy(pool, pool + 5)), void);
50 assert(counter == 0);
51
52 std::allocator_traits<Alloc>::deallocate(alloc, pool, 5);
53 }
54 {
55 using Array = Counted[3][2];
56 using Alloc = std::allocator<Array>;
57 int counter = 0;
58 Alloc alloc;
59 Array* pool = std::allocator_traits<Alloc>::allocate(alloc, 5);
60
61 for (Array* p = pool; p != pool + 5; ++p) {
62 Array& arr = *p;
63 for (int i = 0; i != 3; ++i) {
64 for (int j = 0; j != 2; ++j) {
65 std::allocator_traits<Alloc>::construct(alloc, std::addressof(arr[i][j]), &counter);
66 }
67 }
68 }
69 assert(counter == 5 * 3 * 2);
70
71 std::destroy(pool, pool + 5);
72 ASSERT_SAME_TYPE(decltype(std::destroy(pool, pool + 5)), void);
73 assert(counter == 0);
74
75 std::allocator_traits<Alloc>::deallocate(alloc, pool, 5);
76 }
77
78 return true;
79}
80#endif
81
82template <class It>
83TEST_CONSTEXPR_CXX20 void test() {
84 using Alloc = std::allocator<Counted>;
85 int counter = 0;
86 Alloc alloc;
87 Counted* pool = std::allocator_traits<Alloc>::allocate(a&: alloc, n: 5);
88
89 for (Counted* p = pool; p != pool + 5; ++p)
90 std::allocator_traits<Alloc>::construct(a&: alloc, p: p, args: &counter);
91 assert(counter == 5);
92
93 std::destroy(It(pool), It(pool + 5));
94 ASSERT_SAME_TYPE(decltype(std::destroy(It(pool), It(pool + 5))), void);
95 assert(counter == 0);
96
97 std::allocator_traits<Alloc>::deallocate(a&: alloc, p: pool, n: 5);
98}
99
100TEST_CONSTEXPR_CXX20 bool tests() {
101 test<Counted*>();
102 test<forward_iterator<Counted*>>();
103 return true;
104}
105
106int main(int, char**) {
107 tests();
108#if TEST_STD_VER > 17
109 test_arrays();
110 static_assert(tests());
111 // TODO: Until std::construct_at has support for arrays, it's impossible to test this
112 // in a constexpr context (see https://reviews.llvm.org/D114903).
113 // static_assert(test_arrays());
114#endif
115 return 0;
116}
117

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