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// <memory>
10
11// unique_ptr
12
13// T& unique_ptr::operator[](size_t) const
14
15#include <memory>
16#include <cassert>
17#include <type_traits>
18#include <array>
19
20#include "test_macros.h"
21#include "type_algorithms.h"
22
23static int next = 0;
24struct EnumeratedDefaultCtor {
25 EnumeratedDefaultCtor() : value(0) { value = ++next; }
26 int value;
27};
28
29template <std::size_t Size>
30struct WithTrivialDtor {
31 std::array<char, Size> padding = {'x'};
32 TEST_CONSTEXPR_CXX23 friend bool operator==(WithTrivialDtor const& x, WithTrivialDtor const& y) {
33 return x.padding == y.padding;
34 }
35};
36
37template <std::size_t Size>
38struct WithNonTrivialDtor {
39 std::array<char, Size> padding = {'x'};
40 TEST_CONSTEXPR_CXX23 friend bool operator==(WithNonTrivialDtor const& x, WithNonTrivialDtor const& y) {
41 return x.padding == y.padding;
42 }
43 TEST_CONSTEXPR_CXX23 ~WithNonTrivialDtor() {}
44};
45
46template <class T>
47struct CustomDeleter : std::default_delete<T> {};
48
49struct NoopDeleter {
50 template <class T>
51 TEST_CONSTEXPR_CXX23 void operator()(T*) const {}
52};
53
54TEST_CONSTEXPR_CXX23 bool test() {
55 // Basic test
56 {
57 std::unique_ptr<int[]> p(new int[3]);
58 {
59 int& result = p[0];
60 result = 0;
61 }
62 {
63 int& result = p[1];
64 result = 1;
65 }
66 {
67 int& result = p[2];
68 result = 2;
69 }
70
71 assert(p[0] == 0);
72 assert(p[1] == 1);
73 assert(p[2] == 2);
74 }
75
76 // Ensure that the order of access is correct after initializing a unique_ptr but
77 // before actually modifying any of its elements. The implementation would have to
78 // really try for this not to be the case, but we still check it.
79 //
80 // This requires assigning known values to the elements when they are first constructed,
81 // which requires global state.
82 {
83 if (!TEST_IS_CONSTANT_EVALUATED) {
84 std::unique_ptr<EnumeratedDefaultCtor[]> p(new EnumeratedDefaultCtor[3]);
85 assert(p[0].value == 1);
86 assert(p[1].value == 2);
87 assert(p[2].value == 3);
88 }
89 }
90
91 // Make sure operator[] is const-qualified
92 {
93 std::unique_ptr<int[]> const p(new int[3]);
94 p[0] = 42;
95 assert(p[0] == 42);
96 }
97
98 // Make sure we properly handle types with trivial and non-trivial destructors of different
99 // sizes. This is relevant because some implementations may want to use properties of the
100 // ABI like array cookies and these properties often depend on e.g. the triviality of T's
101 // destructor, T's size and so on.
102#if TEST_STD_VER >= 20 // this test is too painful to write before C++20
103 {
104 using TrickyCookieTypes = types::type_list<
105 WithTrivialDtor<1>,
106 WithTrivialDtor<2>,
107 WithTrivialDtor<3>,
108 WithTrivialDtor<4>,
109 WithTrivialDtor<8>,
110 WithTrivialDtor<16>,
111 WithTrivialDtor<256>,
112 WithNonTrivialDtor<1>,
113 WithNonTrivialDtor<2>,
114 WithNonTrivialDtor<3>,
115 WithNonTrivialDtor<4>,
116 WithNonTrivialDtor<8>,
117 WithNonTrivialDtor<16>,
118 WithNonTrivialDtor<256>>;
119 types::for_each(TrickyCookieTypes(), []<class T> {
120 // Array allocated with `new T[n]`, default deleter
121 {
122 std::unique_ptr<T[], std::default_delete<T[]>> p(new T[3]);
123 assert(p[0] == T());
124 assert(p[1] == T());
125 assert(p[2] == T());
126 }
127
128 // Array allocated with `new T[n]`, custom deleter
129 {
130 std::unique_ptr<T[], CustomDeleter<T[]>> p(new T[3]);
131 assert(p[0] == T());
132 assert(p[1] == T());
133 assert(p[2] == T());
134 }
135
136 // Array not allocated with `new T[n]`, custom deleter
137 //
138 // This test aims to ensure that the implementation doesn't try to use an array cookie
139 // when there is none.
140 {
141 T array[50] = {};
142 std::unique_ptr<T[], NoopDeleter> p(&array[0]);
143 assert(p[0] == T());
144 assert(p[1] == T());
145 assert(p[2] == T());
146 }
147 });
148 }
149#endif // C++20
150
151 return true;
152}
153
154int main(int, char**) {
155 test();
156#if TEST_STD_VER >= 23
157 static_assert(test());
158#endif
159
160 return 0;
161}
162

source code of libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.observers/op_subscript.runtime.pass.cpp