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
21struct B
22{
23 static int count;
24
25 B() {++count;}
26 B(const B&) {++count;}
27 virtual ~B() {--count;}
28};
29
30int B::count = 0;
31
32struct 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
42int A::count = 0;
43
44struct C
45{
46 static int count;
47
48 C() {++count;}
49 C(const C&) {++count;}
50 virtual ~C() {--count;}
51};
52
53int C::count = 0;
54
55class private_delete_op
56{
57 static void operator delete (void *p) {
58 return delete static_cast<char*>(p);
59 }
60public:
61 static void operator delete[] (void *p) {
62 return delete[] static_cast<char*>(p);
63 }
64};
65
66class private_delete_arr_op
67{
68 static void operator delete[] (void *p) {
69 return delete[] static_cast<char*>(p);
70 }
71public:
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
79static_assert(!std::is_constructible<std::shared_ptr<int>, const std::shared_ptr<long>&>::value, "");
80static_assert( std::is_constructible<std::shared_ptr<B>, const std::shared_ptr<A>&>::value, "");
81static_assert( std::is_constructible<std::shared_ptr<const A>, const std::shared_ptr<A>&>::value, "");
82static_assert(!std::is_constructible<std::shared_ptr<A>, const std::shared_ptr<const A>&>::value, "");
83
84#if TEST_STD_VER >= 17
85static_assert(!std::is_constructible<std::shared_ptr<int>, const std::shared_ptr<int[]>&>::value, "");
86static_assert(!std::is_constructible<std::shared_ptr<int>, const std::shared_ptr<int[5]>&>::value, "");
87static_assert(!std::is_constructible<std::shared_ptr<int[]>, const std::shared_ptr<int>&>::value, "");
88static_assert( std::is_constructible<std::shared_ptr<int[]>, const std::shared_ptr<int[5]>&>::value, "");
89static_assert(!std::is_constructible<std::shared_ptr<int[5]>, const std::shared_ptr<int>&>::value, "");
90static_assert(!std::is_constructible<std::shared_ptr<int[5]>, const std::shared_ptr<int[]>&>::value, "");
91static_assert(!std::is_constructible<std::shared_ptr<int[7]>, const std::shared_ptr<int[5]>&>::value, "");
92#endif
93
94int 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

source code of libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/shared_ptr_Y.pass.cpp