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 // template <class T, class ...Args> 14 // constexpr T* construct_at(T* location, Args&& ...args); 15 16 #include <cassert> 17 #include <cstddef> 18 #include <memory> 19 #include <utility> 20 21 #include "test_iterators.h" 22 23 struct Foo { 24 constexpr Foo() { } 25 constexpr Foo(int a, char b, double c) : a_(a), b_(b), c_(c) { } 26 constexpr Foo(int a, char b, double c, int* count) : Foo(a, b, c) { *count += 1; } 27 constexpr bool operator==(Foo const& other) const { 28 return a_ == other.a_ && b_ == other.b_ && c_ == other.c_; 29 } 30 31 private: 32 int a_; 33 char b_; 34 double c_; 35 }; 36 37 struct Counted { 38 int& count_; 39 constexpr Counted(int& count) : count_(count) { ++count; } 40 constexpr Counted(Counted const& that) : count_(that.count_) { ++count_; } 41 constexpr ~Counted() { --count_; } 42 }; 43 44 constexpr bool test() 45 { 46 { 47 int i = 99; 48 int* res = std::construct_at(&i); 49 assert(res == &i); 50 assert(*res == 0); 51 } 52 53 { 54 int i = 0; 55 int* res = std::construct_at(&i, 42); 56 assert(res == &i); 57 assert(*res == 42); 58 } 59 60 { 61 Foo foo = {}; 62 int count = 0; 63 Foo* res = std::construct_at(&foo, 42, 'x', 123.89, &count); 64 assert(res == &foo); 65 assert(*res == Foo(42, 'x', 123.89)); 66 assert(count == 1); 67 } 68 69 { 70 std::allocator<Counted> a; 71 Counted* p = a.allocate(2); 72 int count = 0; 73 std::construct_at(p, count); 74 assert(count == 1); 75 std::construct_at(p+1, count); 76 assert(count == 2); 77 (p+1)->~Counted(); 78 assert(count == 1); 79 p->~Counted(); 80 assert(count == 0); 81 a.deallocate(p, 2); 82 } 83 84 return true; 85 } 86 87 template <class ...Args> 88 constexpr bool can_construct_at = requires { 89 std::construct_at(std::declval<Args>()...); 90 }; 91 92 // Check that SFINAE works. 93 static_assert( can_construct_at<int*, int>); 94 static_assert( can_construct_at<Foo*, int, char, double>); 95 static_assert(!can_construct_at<Foo*, int, char>); 96 static_assert(!can_construct_at<Foo*, int, char, double, int>); 97 static_assert(!can_construct_at<std::nullptr_t, int, char, double>); 98 static_assert(!can_construct_at<int*, int, char, double>); 99 static_assert(!can_construct_at<contiguous_iterator<Foo*>, int, char, double>); 100 // Can't construct function pointers. 101 static_assert(!can_construct_at<int(*)()>); 102 static_assert(!can_construct_at<int(*)(), std::nullptr_t>); 103 104 int main(int, char**) { 105 test(); 106 static_assert(test()); 107 return 0; 108 } 109