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.
30LIBCPP_STATIC_ASSERT(std::is_class_v<decltype(std::ranges::construct_at)>);
31
32struct 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
44ASSERT_SAME_TYPE(decltype(std::ranges::construct_at((int*)nullptr)), int*);
45ASSERT_SAME_TYPE(decltype(std::ranges::construct_at((Foo*)nullptr)), Foo*);
46
47struct 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
55constexpr 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(n: 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(first: out, last: out + 1);
99 alloc.deallocate(p: out, t: 2);
100 }
101
102 // Works with const pointers.
103 {
104 int x = 1;
105 const int* ptr = &x;
106
107 const int* result = std::ranges::construct_at(ptr, 42);
108 assert(result == ptr);
109 assert(x == 42);
110 }
111
112 return true;
113}
114
115constexpr bool can_construct_at(auto&&... args)
116 requires requires { std::ranges::construct_at(decltype(args)(args)...); }
117 { return true; }
118
119constexpr bool can_construct_at(auto&&...) { return false; }
120
121// Check that SFINAE works.
122static_assert( can_construct_at((Foo*)nullptr, 1, 2));
123static_assert(!can_construct_at((Foo*)nullptr, 1));
124static_assert(!can_construct_at((Foo*)nullptr, 1, 2, 3));
125static_assert(!can_construct_at(nullptr, 1, 2));
126static_assert(!can_construct_at((int*)nullptr, 1, 2));
127static_assert(!can_construct_at(contiguous_iterator<Foo*>(), 1, 2));
128// Can't construct function pointers.
129static_assert(!can_construct_at((int(*)())nullptr));
130static_assert(!can_construct_at((int(*)())nullptr, nullptr));
131// TODO(varconst): check that array types work once D114649 implementing LWG3639 lands.
132
133int main(int, char**) {
134 test();
135 static_assert(test());
136
137 return 0;
138}
139

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