117 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++03, c++11, c++1410 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 > 1732constexpr 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#endif81 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(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 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 > 17109 test_arrays();110 static_assert(tests());111 // TODO: Until std::construct_at has support for arrays, it's impossible to test this112 // in a constexpr context (see https://reviews.llvm.org/D114903).113 // static_assert(test_arrays());114#endif115 return 0;116}117