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 | // shared_ptr |
12 | |
13 | // template<class Y> shared_ptr(const shared_ptr<Y>& r); |
14 | |
15 | #include <memory> |
16 | #include <type_traits> |
17 | #include <cassert> |
18 | |
19 | #include "test_macros.h" |
20 | |
21 | struct B |
22 | { |
23 | static int count; |
24 | |
25 | B() {++count;} |
26 | B(const B&) {++count;} |
27 | virtual ~B() {--count;} |
28 | }; |
29 | |
30 | int B::count = 0; |
31 | |
32 | struct A |
33 | : public B |
34 | { |
35 | static int count; |
36 | |
37 | A() {++count;} |
38 | A(const A& other) : B(other) {++count;} |
39 | ~A() {--count;} |
40 | }; |
41 | |
42 | int A::count = 0; |
43 | |
44 | struct C |
45 | { |
46 | static int count; |
47 | |
48 | C() {++count;} |
49 | C(const C&) {++count;} |
50 | virtual ~C() {--count;} |
51 | }; |
52 | |
53 | int C::count = 0; |
54 | |
55 | class private_delete_op |
56 | { |
57 | static void operator delete (void *p) { |
58 | return delete static_cast<char*>(p); |
59 | } |
60 | public: |
61 | static void operator delete[] (void *p) { |
62 | return delete[] static_cast<char*>(p); |
63 | } |
64 | }; |
65 | |
66 | class private_delete_arr_op |
67 | { |
68 | static void operator delete[] (void *p) { |
69 | return delete[] static_cast<char*>(p); |
70 | } |
71 | public: |
72 | static void operator delete (void *p) { |
73 | return delete static_cast<char*>(p); |
74 | } |
75 | }; |
76 | |
77 | // https://llvm.org/PR60258 |
78 | // Invalid constructor SFINAE for std::shared_ptr's array ctors |
79 | static_assert(!std::is_constructible<std::shared_ptr<int>, const std::shared_ptr<long>&>::value, "" ); |
80 | static_assert( std::is_constructible<std::shared_ptr<B>, const std::shared_ptr<A>&>::value, "" ); |
81 | static_assert( std::is_constructible<std::shared_ptr<const A>, const std::shared_ptr<A>&>::value, "" ); |
82 | static_assert(!std::is_constructible<std::shared_ptr<A>, const std::shared_ptr<const A>&>::value, "" ); |
83 | |
84 | #if TEST_STD_VER >= 17 |
85 | static_assert(!std::is_constructible<std::shared_ptr<int>, const std::shared_ptr<int[]>&>::value, "" ); |
86 | static_assert(!std::is_constructible<std::shared_ptr<int>, const std::shared_ptr<int[5]>&>::value, "" ); |
87 | static_assert(!std::is_constructible<std::shared_ptr<int[]>, const std::shared_ptr<int>&>::value, "" ); |
88 | static_assert( std::is_constructible<std::shared_ptr<int[]>, const std::shared_ptr<int[5]>&>::value, "" ); |
89 | static_assert(!std::is_constructible<std::shared_ptr<int[5]>, const std::shared_ptr<int>&>::value, "" ); |
90 | static_assert(!std::is_constructible<std::shared_ptr<int[5]>, const std::shared_ptr<int[]>&>::value, "" ); |
91 | static_assert(!std::is_constructible<std::shared_ptr<int[7]>, const std::shared_ptr<int[5]>&>::value, "" ); |
92 | #endif |
93 | |
94 | int main(int, char**) |
95 | { |
96 | static_assert(( std::is_convertible<std::shared_ptr<A>, std::shared_ptr<B> >::value), "" ); |
97 | static_assert((!std::is_convertible<std::shared_ptr<B>, std::shared_ptr<A> >::value), "" ); |
98 | static_assert((!std::is_convertible<std::shared_ptr<A>, std::shared_ptr<C> >::value), "" ); |
99 | { |
100 | const std::shared_ptr<A> pA(new A); |
101 | assert(pA.use_count() == 1); |
102 | assert(B::count == 1); |
103 | assert(A::count == 1); |
104 | { |
105 | std::shared_ptr<B> pB(pA); |
106 | assert(B::count == 1); |
107 | assert(A::count == 1); |
108 | assert(pB.use_count() == 2); |
109 | assert(pA.use_count() == 2); |
110 | assert(pA.get() == pB.get()); |
111 | } |
112 | assert(pA.use_count() == 1); |
113 | assert(B::count == 1); |
114 | assert(A::count == 1); |
115 | } |
116 | assert(B::count == 0); |
117 | assert(A::count == 0); |
118 | { |
119 | std::shared_ptr<A> pA; |
120 | assert(pA.use_count() == 0); |
121 | assert(B::count == 0); |
122 | assert(A::count == 0); |
123 | { |
124 | std::shared_ptr<B> pB(pA); |
125 | assert(B::count == 0); |
126 | assert(A::count == 0); |
127 | assert(pB.use_count() == 0); |
128 | assert(pA.use_count() == 0); |
129 | assert(pA.get() == pB.get()); |
130 | } |
131 | assert(pA.use_count() == 0); |
132 | assert(B::count == 0); |
133 | assert(A::count == 0); |
134 | } |
135 | assert(B::count == 0); |
136 | assert(A::count == 0); |
137 | |
138 | // This should work in C++03 but we get errors when trying to do SFINAE with the delete operator. |
139 | // GCC also complains about this. |
140 | #if TEST_STD_VER >= 11 && !defined(TEST_COMPILER_GCC) |
141 | { |
142 | // LWG2874: Make sure that when T (for std::shared_ptr<T>) is an array type, |
143 | // this constructor only participates in overload resolution when |
144 | // `delete[] p` is well formed. And when T is not an array type, |
145 | // this constructor only participates in overload resolution when |
146 | // `delete p` is well formed. |
147 | static_assert(!std::is_constructible<std::shared_ptr<private_delete_op>, |
148 | private_delete_op*>::value, "" ); |
149 | static_assert(!std::is_constructible<std::shared_ptr<private_delete_arr_op[4]>, |
150 | private_delete_arr_op*>::value, "" ); |
151 | } |
152 | #endif |
153 | |
154 | #if TEST_STD_VER > 14 |
155 | { |
156 | std::shared_ptr<A[]> p1(new A[8]); |
157 | assert(p1.use_count() == 1); |
158 | assert(A::count == 8); |
159 | { |
160 | std::shared_ptr<const A[]> p2(p1); |
161 | assert(A::count == 8); |
162 | assert(p2.use_count() == 2); |
163 | assert(p1.use_count() == 2); |
164 | assert(p1.get() == p2.get()); |
165 | } |
166 | assert(p1.use_count() == 1); |
167 | assert(A::count == 8); |
168 | } |
169 | assert(A::count == 0); |
170 | #endif |
171 | |
172 | { |
173 | std::shared_ptr<A const> pA(new A); |
174 | std::shared_ptr<B const> pB(pA); |
175 | assert(pB.get() == pA.get()); |
176 | } |
177 | |
178 | return 0; |
179 | } |
180 | |