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, c++17 10 11 // <memory> 12 // 13 // namespace ranges { 14 // template<class T, class... Args> 15 // constexpr T* construct_at(T* location, Args&&... args); // since C++20 16 // } 17 18 #include <cassert> 19 #include <initializer_list> 20 #include <memory> 21 #include <type_traits> 22 23 #include "test_iterators.h" 24 #include "test_macros.h" 25 26 // TODO(varconst): consolidate the ADL checks into a single file. 27 // Because this is a variable and not a function, it's guaranteed that ADL won't be used. However, 28 // implementations are allowed to use a different mechanism to achieve this effect, so this check is 29 // libc++-specific. 30 LIBCPP_STATIC_ASSERT(std::is_class_v<decltype(std::ranges::construct_at)>); 31 32 struct Foo { 33 int x = 0; 34 int y = 0; 35 36 constexpr Foo() = default; 37 constexpr explicit Foo(int set_x, int set_y) : x(set_x), y(set_y) {} 38 constexpr Foo(std::initializer_list<int>); 39 40 void operator&() const = delete; 41 void operator,(auto&&) const = delete; 42 }; 43 44 ASSERT_SAME_TYPE(decltype(std::ranges::construct_at((int*)nullptr)), int*); 45 ASSERT_SAME_TYPE(decltype(std::ranges::construct_at((Foo*)nullptr)), Foo*); 46 47 struct Counted { 48 int& count; 49 50 constexpr Counted(int& count_ref) : count(count_ref) { ++count; } 51 constexpr Counted(const Counted& rhs) : count(rhs.count) { ++count; } 52 constexpr ~Counted() { --count; } 53 }; 54 55 constexpr bool test() { 56 // Value initialization. 57 { 58 int x = 1; 59 60 int* result = std::ranges::construct_at(&x); 61 assert(result == &x); 62 assert(x == 0); 63 } 64 65 // Copy initialization. 66 { 67 int x = 1; 68 69 int* result = std::ranges::construct_at(&x, 42); 70 assert(result == &x); 71 assert(x == 42); 72 } 73 74 // Explicit multiargument constructor; also checks that the initializer list constructor is not invoked. 75 { 76 Foo f; 77 78 Foo* result = std::ranges::construct_at(std::addressof(f), 42, 123); 79 assert(result == std::addressof(f)); 80 assert(f.x == 42); 81 assert(f.y == 123); 82 } 83 84 // Works with buffers of uninitialized memory. 85 { 86 std::allocator<Counted> alloc; 87 Counted* out = alloc.allocate(2); 88 int count = 0; 89 90 Counted* result = std::ranges::construct_at(out, count); 91 assert(result == out); 92 assert(count == 1); 93 94 result = std::ranges::construct_at(out + 1, count); 95 assert(result == out + 1); 96 assert(count == 2); 97 98 std::destroy(out, out + 1); 99 alloc.deallocate(out, 2); 100 } 101 102 return true; 103 } 104 105 constexpr bool can_construct_at(auto&&... args) 106 requires requires { std::ranges::construct_at(decltype(args)(args)...); } 107 { return true; } 108 109 constexpr bool can_construct_at(auto&&...) { return false; } 110 111 // Check that SFINAE works. 112 static_assert( can_construct_at((Foo*)nullptr, 1, 2)); 113 static_assert(!can_construct_at((Foo*)nullptr, 1)); 114 static_assert(!can_construct_at((Foo*)nullptr, 1, 2, 3)); 115 static_assert(!can_construct_at(nullptr, 1, 2)); 116 static_assert(!can_construct_at((int*)nullptr, 1, 2)); 117 static_assert(!can_construct_at(contiguous_iterator<Foo*>(), 1, 2)); 118 // Can't construct function pointers. 119 static_assert(!can_construct_at((int(*)())nullptr)); 120 static_assert(!can_construct_at((int(*)())nullptr, nullptr)); 121 // TODO(varconst): check that array types work once D114649 implementing LWG3639 lands. 122 123 int main(int, char**) { 124 test(); 125 static_assert(test()); 126 127 return 0; 128 } 129