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

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