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 23 struct 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 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 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 82 template <class It> 83 TEST_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(alloc, 5); 88 89 for (Counted* p = pool; p != pool + 5; ++p) 90 std::allocator_traits<Alloc>::construct(alloc, p, &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(alloc, pool, 5); 98 } 99 100 TEST_CONSTEXPR_CXX20 bool tests() { 101 test<Counted*>(); 102 test<forward_iterator<Counted*>>(); 103 return true; 104 } 105 106 int 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