1*35238bceSAndroid Build Coastguard Worker #ifndef _DEUNIQUEPTR_HPP
2*35238bceSAndroid Build Coastguard Worker #define _DEUNIQUEPTR_HPP
3*35238bceSAndroid Build Coastguard Worker /*-------------------------------------------------------------------------
4*35238bceSAndroid Build Coastguard Worker * drawElements C++ Base Library
5*35238bceSAndroid Build Coastguard Worker * -----------------------------
6*35238bceSAndroid Build Coastguard Worker *
7*35238bceSAndroid Build Coastguard Worker * Copyright 2014 The Android Open Source Project
8*35238bceSAndroid Build Coastguard Worker *
9*35238bceSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
10*35238bceSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
11*35238bceSAndroid Build Coastguard Worker * You may obtain a copy of the License at
12*35238bceSAndroid Build Coastguard Worker *
13*35238bceSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
14*35238bceSAndroid Build Coastguard Worker *
15*35238bceSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
16*35238bceSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
17*35238bceSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18*35238bceSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
19*35238bceSAndroid Build Coastguard Worker * limitations under the License.
20*35238bceSAndroid Build Coastguard Worker *
21*35238bceSAndroid Build Coastguard Worker *//*!
22*35238bceSAndroid Build Coastguard Worker * \file
23*35238bceSAndroid Build Coastguard Worker * \brief Unique pointer.
24*35238bceSAndroid Build Coastguard Worker *//*--------------------------------------------------------------------*/
25*35238bceSAndroid Build Coastguard Worker
26*35238bceSAndroid Build Coastguard Worker #include "deDefs.hpp"
27*35238bceSAndroid Build Coastguard Worker
28*35238bceSAndroid Build Coastguard Worker namespace de
29*35238bceSAndroid Build Coastguard Worker {
30*35238bceSAndroid Build Coastguard Worker
31*35238bceSAndroid Build Coastguard Worker //! Unique pointer self-test.
32*35238bceSAndroid Build Coastguard Worker void UniquePtr_selfTest(void);
33*35238bceSAndroid Build Coastguard Worker
34*35238bceSAndroid Build Coastguard Worker // Hide implementation-private types in a details namespace.
35*35238bceSAndroid Build Coastguard Worker namespace details
36*35238bceSAndroid Build Coastguard Worker {
37*35238bceSAndroid Build Coastguard Worker
38*35238bceSAndroid Build Coastguard Worker //! Auxiliary struct used to pass references between unique pointers. To
39*35238bceSAndroid Build Coastguard Worker //! ensure that managed pointers are deleted exactly once, this type should
40*35238bceSAndroid Build Coastguard Worker //! not appear in user code.
41*35238bceSAndroid Build Coastguard Worker template <typename T, class D>
42*35238bceSAndroid Build Coastguard Worker struct PtrData
43*35238bceSAndroid Build Coastguard Worker {
PtrDatade::details::PtrData44*35238bceSAndroid Build Coastguard Worker PtrData(T *p, D d) : ptr(p), deleter(d)
45*35238bceSAndroid Build Coastguard Worker {
46*35238bceSAndroid Build Coastguard Worker }
47*35238bceSAndroid Build Coastguard Worker
48*35238bceSAndroid Build Coastguard Worker template <typename T2, class D2>
PtrDatade::details::PtrData49*35238bceSAndroid Build Coastguard Worker PtrData(const PtrData<T2, D2> &d) : ptr(d.ptr)
50*35238bceSAndroid Build Coastguard Worker , deleter(d.deleter)
51*35238bceSAndroid Build Coastguard Worker {
52*35238bceSAndroid Build Coastguard Worker }
53*35238bceSAndroid Build Coastguard Worker
54*35238bceSAndroid Build Coastguard Worker T *ptr;
55*35238bceSAndroid Build Coastguard Worker D deleter;
56*35238bceSAndroid Build Coastguard Worker };
57*35238bceSAndroid Build Coastguard Worker
58*35238bceSAndroid Build Coastguard Worker template <typename T, class D>
59*35238bceSAndroid Build Coastguard Worker class UniqueBase
60*35238bceSAndroid Build Coastguard Worker {
61*35238bceSAndroid Build Coastguard Worker public:
62*35238bceSAndroid Build Coastguard Worker typedef T element_type;
63*35238bceSAndroid Build Coastguard Worker typedef D deleter_type;
64*35238bceSAndroid Build Coastguard Worker
get(void) const65*35238bceSAndroid Build Coastguard Worker T *get(void) const throw()
66*35238bceSAndroid Build Coastguard Worker {
67*35238bceSAndroid Build Coastguard Worker return m_data.ptr;
68*35238bceSAndroid Build Coastguard Worker } //!< Get stored pointer.
getDeleter(void) const69*35238bceSAndroid Build Coastguard Worker D getDeleter(void) const throw()
70*35238bceSAndroid Build Coastguard Worker {
71*35238bceSAndroid Build Coastguard Worker return m_data.deleter;
72*35238bceSAndroid Build Coastguard Worker }
operator ->(void) const73*35238bceSAndroid Build Coastguard Worker T *operator->(void) const throw()
74*35238bceSAndroid Build Coastguard Worker {
75*35238bceSAndroid Build Coastguard Worker return get();
76*35238bceSAndroid Build Coastguard Worker } //!< Get stored pointer.
operator *(void) const77*35238bceSAndroid Build Coastguard Worker T &operator*(void) const throw()
78*35238bceSAndroid Build Coastguard Worker {
79*35238bceSAndroid Build Coastguard Worker return *get();
80*35238bceSAndroid Build Coastguard Worker } //!< De-reference stored pointer.
operator bool(void) const81*35238bceSAndroid Build Coastguard Worker operator bool(void) const throw()
82*35238bceSAndroid Build Coastguard Worker {
83*35238bceSAndroid Build Coastguard Worker return !!get();
84*35238bceSAndroid Build Coastguard Worker }
85*35238bceSAndroid Build Coastguard Worker
86*35238bceSAndroid Build Coastguard Worker protected:
UniqueBase(T * ptr,D deleter)87*35238bceSAndroid Build Coastguard Worker UniqueBase(T *ptr, D deleter) : m_data(ptr, deleter)
88*35238bceSAndroid Build Coastguard Worker {
89*35238bceSAndroid Build Coastguard Worker }
UniqueBase(PtrData<T,D> data)90*35238bceSAndroid Build Coastguard Worker UniqueBase(PtrData<T, D> data) : m_data(data)
91*35238bceSAndroid Build Coastguard Worker {
92*35238bceSAndroid Build Coastguard Worker }
93*35238bceSAndroid Build Coastguard Worker ~UniqueBase(void);
94*35238bceSAndroid Build Coastguard Worker
95*35238bceSAndroid Build Coastguard Worker void reset(void); //!< Delete previous pointer, set to null.
96*35238bceSAndroid Build Coastguard Worker PtrData<T, D> releaseData(void) throw(); //!< Relinquish ownership, return pointer data.
97*35238bceSAndroid Build Coastguard Worker void assignData(PtrData<T, D> data); //!< Set new pointer, delete previous pointer.
98*35238bceSAndroid Build Coastguard Worker
99*35238bceSAndroid Build Coastguard Worker private:
100*35238bceSAndroid Build Coastguard Worker PtrData<T, D> m_data;
101*35238bceSAndroid Build Coastguard Worker };
102*35238bceSAndroid Build Coastguard Worker
103*35238bceSAndroid Build Coastguard Worker template <typename T, class D>
~UniqueBase(void)104*35238bceSAndroid Build Coastguard Worker UniqueBase<T, D>::~UniqueBase(void)
105*35238bceSAndroid Build Coastguard Worker {
106*35238bceSAndroid Build Coastguard Worker reset();
107*35238bceSAndroid Build Coastguard Worker }
108*35238bceSAndroid Build Coastguard Worker
109*35238bceSAndroid Build Coastguard Worker template <typename T, class D>
reset(void)110*35238bceSAndroid Build Coastguard Worker void UniqueBase<T, D>::reset(void)
111*35238bceSAndroid Build Coastguard Worker {
112*35238bceSAndroid Build Coastguard Worker if (m_data.ptr != DE_NULL)
113*35238bceSAndroid Build Coastguard Worker {
114*35238bceSAndroid Build Coastguard Worker m_data.deleter(m_data.ptr);
115*35238bceSAndroid Build Coastguard Worker m_data.ptr = DE_NULL;
116*35238bceSAndroid Build Coastguard Worker }
117*35238bceSAndroid Build Coastguard Worker }
118*35238bceSAndroid Build Coastguard Worker
119*35238bceSAndroid Build Coastguard Worker template <typename T, class D>
releaseData(void)120*35238bceSAndroid Build Coastguard Worker PtrData<T, D> UniqueBase<T, D>::releaseData(void) throw()
121*35238bceSAndroid Build Coastguard Worker {
122*35238bceSAndroid Build Coastguard Worker PtrData<T, D> data = m_data;
123*35238bceSAndroid Build Coastguard Worker m_data.ptr = DE_NULL;
124*35238bceSAndroid Build Coastguard Worker return data;
125*35238bceSAndroid Build Coastguard Worker }
126*35238bceSAndroid Build Coastguard Worker
127*35238bceSAndroid Build Coastguard Worker template <typename T, class D>
assignData(PtrData<T,D> data)128*35238bceSAndroid Build Coastguard Worker void UniqueBase<T, D>::assignData(PtrData<T, D> data)
129*35238bceSAndroid Build Coastguard Worker {
130*35238bceSAndroid Build Coastguard Worker if (data.ptr != m_data.ptr)
131*35238bceSAndroid Build Coastguard Worker {
132*35238bceSAndroid Build Coastguard Worker reset();
133*35238bceSAndroid Build Coastguard Worker m_data = data;
134*35238bceSAndroid Build Coastguard Worker }
135*35238bceSAndroid Build Coastguard Worker }
136*35238bceSAndroid Build Coastguard Worker
137*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
138*35238bceSAndroid Build Coastguard Worker * \brief Movable unique pointer
139*35238bceSAndroid Build Coastguard Worker *
140*35238bceSAndroid Build Coastguard Worker * A MovePtr is smart pointer that retains sole ownership of a pointer and
141*35238bceSAndroid Build Coastguard Worker * destroys it when it is destroyed (for example when it goes out of scope).
142*35238bceSAndroid Build Coastguard Worker *
143*35238bceSAndroid Build Coastguard Worker * A MovePtr can be copied and assigned to. The pointer ownership is moved to
144*35238bceSAndroid Build Coastguard Worker * the newly constructer or assigned-to MovePtr. Upon assignment to a
145*35238bceSAndroid Build Coastguard Worker * MovePtr, the previously managed pointer is deleted.
146*35238bceSAndroid Build Coastguard Worker *
147*35238bceSAndroid Build Coastguard Worker *//*--------------------------------------------------------------------*/
148*35238bceSAndroid Build Coastguard Worker template <typename T, class Deleter = DefaultDeleter<T>>
149*35238bceSAndroid Build Coastguard Worker class MovePtr : public UniqueBase<T, Deleter>
150*35238bceSAndroid Build Coastguard Worker {
151*35238bceSAndroid Build Coastguard Worker public:
MovePtr(void)152*35238bceSAndroid Build Coastguard Worker MovePtr(void) : UniqueBase<T, Deleter>(DE_NULL, Deleter())
153*35238bceSAndroid Build Coastguard Worker {
154*35238bceSAndroid Build Coastguard Worker }
MovePtr(T * ptr,Deleter deleter=Deleter ())155*35238bceSAndroid Build Coastguard Worker explicit MovePtr(T *ptr, Deleter deleter = Deleter()) : UniqueBase<T, Deleter>(ptr, deleter)
156*35238bceSAndroid Build Coastguard Worker {
157*35238bceSAndroid Build Coastguard Worker }
MovePtr(MovePtr<T,Deleter> & other)158*35238bceSAndroid Build Coastguard Worker MovePtr(MovePtr<T, Deleter> &other) : UniqueBase<T, Deleter>(other.releaseData())
159*35238bceSAndroid Build Coastguard Worker {
160*35238bceSAndroid Build Coastguard Worker }
161*35238bceSAndroid Build Coastguard Worker
162*35238bceSAndroid Build Coastguard Worker MovePtr &operator=(MovePtr<T, Deleter> &other);
163*35238bceSAndroid Build Coastguard Worker T *release(void) throw();
clear(void)164*35238bceSAndroid Build Coastguard Worker void clear(void)
165*35238bceSAndroid Build Coastguard Worker {
166*35238bceSAndroid Build Coastguard Worker this->reset();
167*35238bceSAndroid Build Coastguard Worker }
168*35238bceSAndroid Build Coastguard Worker
169*35238bceSAndroid Build Coastguard Worker // These implicit by-value conversions to and from a PtrData are used to
170*35238bceSAndroid Build Coastguard Worker // allow copying a MovePtr by value when returning from a function. To
171*35238bceSAndroid Build Coastguard Worker // ensure that the managed pointer gets deleted exactly once, the PtrData
172*35238bceSAndroid Build Coastguard Worker // should only exist as a temporary conversion step between two MovePtrs.
MovePtr(PtrData<T,Deleter> data)173*35238bceSAndroid Build Coastguard Worker MovePtr(PtrData<T, Deleter> data) : UniqueBase<T, Deleter>(data)
174*35238bceSAndroid Build Coastguard Worker {
175*35238bceSAndroid Build Coastguard Worker }
176*35238bceSAndroid Build Coastguard Worker MovePtr &operator=(PtrData<T, Deleter> data);
177*35238bceSAndroid Build Coastguard Worker
178*35238bceSAndroid Build Coastguard Worker template <typename U, class Del2>
operator PtrData<U,Del2>(void)179*35238bceSAndroid Build Coastguard Worker operator PtrData<U, Del2>(void)
180*35238bceSAndroid Build Coastguard Worker {
181*35238bceSAndroid Build Coastguard Worker return this->releaseData();
182*35238bceSAndroid Build Coastguard Worker }
183*35238bceSAndroid Build Coastguard Worker };
184*35238bceSAndroid Build Coastguard Worker
185*35238bceSAndroid Build Coastguard Worker template <typename T, class D>
operator =(PtrData<T,D> data)186*35238bceSAndroid Build Coastguard Worker MovePtr<T, D> &MovePtr<T, D>::operator=(PtrData<T, D> data)
187*35238bceSAndroid Build Coastguard Worker {
188*35238bceSAndroid Build Coastguard Worker this->assignData(data);
189*35238bceSAndroid Build Coastguard Worker return *this;
190*35238bceSAndroid Build Coastguard Worker }
191*35238bceSAndroid Build Coastguard Worker
192*35238bceSAndroid Build Coastguard Worker template <typename T, class D>
operator =(MovePtr<T,D> & other)193*35238bceSAndroid Build Coastguard Worker MovePtr<T, D> &MovePtr<T, D>::operator=(MovePtr<T, D> &other)
194*35238bceSAndroid Build Coastguard Worker {
195*35238bceSAndroid Build Coastguard Worker return (*this = other.releaseData());
196*35238bceSAndroid Build Coastguard Worker }
197*35238bceSAndroid Build Coastguard Worker
198*35238bceSAndroid Build Coastguard Worker //! Steal the managed pointer. The caller is responsible for explicitly
199*35238bceSAndroid Build Coastguard Worker //! deleting the returned pointer.
200*35238bceSAndroid Build Coastguard Worker template <typename T, class D>
release(void)201*35238bceSAndroid Build Coastguard Worker inline T *MovePtr<T, D>::release(void) throw()
202*35238bceSAndroid Build Coastguard Worker {
203*35238bceSAndroid Build Coastguard Worker return this->releaseData().ptr;
204*35238bceSAndroid Build Coastguard Worker }
205*35238bceSAndroid Build Coastguard Worker
206*35238bceSAndroid Build Coastguard Worker //! Construct a MovePtr from a pointer.
207*35238bceSAndroid Build Coastguard Worker template <typename T>
movePtr(T * ptr)208*35238bceSAndroid Build Coastguard Worker inline MovePtr<T> movePtr(T *ptr)
209*35238bceSAndroid Build Coastguard Worker {
210*35238bceSAndroid Build Coastguard Worker return MovePtr<T>(ptr);
211*35238bceSAndroid Build Coastguard Worker }
212*35238bceSAndroid Build Coastguard Worker
213*35238bceSAndroid Build Coastguard Worker //! Allocate and construct an object and return its address as a MovePtr.
214*35238bceSAndroid Build Coastguard Worker template <typename T>
newMovePtr(void)215*35238bceSAndroid Build Coastguard Worker inline MovePtr<T> newMovePtr(void)
216*35238bceSAndroid Build Coastguard Worker {
217*35238bceSAndroid Build Coastguard Worker return MovePtr<T>(new T());
218*35238bceSAndroid Build Coastguard Worker }
219*35238bceSAndroid Build Coastguard Worker template <typename T, typename P0>
newMovePtr(P0 p0)220*35238bceSAndroid Build Coastguard Worker inline MovePtr<T> newMovePtr(P0 p0)
221*35238bceSAndroid Build Coastguard Worker {
222*35238bceSAndroid Build Coastguard Worker return MovePtr<T>(new T(p0));
223*35238bceSAndroid Build Coastguard Worker }
224*35238bceSAndroid Build Coastguard Worker template <typename T, typename P0, typename P1>
newMovePtr(P0 p0,P1 p1)225*35238bceSAndroid Build Coastguard Worker inline MovePtr<T> newMovePtr(P0 p0, P1 p1)
226*35238bceSAndroid Build Coastguard Worker {
227*35238bceSAndroid Build Coastguard Worker return MovePtr<T>(new T(p0, p1));
228*35238bceSAndroid Build Coastguard Worker }
229*35238bceSAndroid Build Coastguard Worker template <typename T, typename P0, typename P1, typename P2>
newMovePtr(P0 p0,P1 p1,P2 p2)230*35238bceSAndroid Build Coastguard Worker inline MovePtr<T> newMovePtr(P0 p0, P1 p1, P2 p2)
231*35238bceSAndroid Build Coastguard Worker {
232*35238bceSAndroid Build Coastguard Worker return MovePtr<T>(new T(p0, p1, p2));
233*35238bceSAndroid Build Coastguard Worker }
234*35238bceSAndroid Build Coastguard Worker
235*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
236*35238bceSAndroid Build Coastguard Worker * \brief Unique pointer
237*35238bceSAndroid Build Coastguard Worker *
238*35238bceSAndroid Build Coastguard Worker * UniquePtr is smart pointer that retains sole ownership of a pointer
239*35238bceSAndroid Build Coastguard Worker * and destroys it when UniquePtr is destroyed (for example when UniquePtr
240*35238bceSAndroid Build Coastguard Worker * goes out of scope).
241*35238bceSAndroid Build Coastguard Worker *
242*35238bceSAndroid Build Coastguard Worker * UniquePtr is not copyable or assignable. Pointer ownership can be transferred
243*35238bceSAndroid Build Coastguard Worker * from a UniquePtr only explicitly with the move() member function.
244*35238bceSAndroid Build Coastguard Worker *
245*35238bceSAndroid Build Coastguard Worker * A UniquePtr can be constructed from a MovePtr. In this case it assumes
246*35238bceSAndroid Build Coastguard Worker * ownership of the pointer from the MovePtr. Because a UniquePtr cannot be
247*35238bceSAndroid Build Coastguard Worker * copied, direct initialization syntax must be used, i.e.:
248*35238bceSAndroid Build Coastguard Worker *
249*35238bceSAndroid Build Coastguard Worker * MovePtr<Foo> createFoo (void);
250*35238bceSAndroid Build Coastguard Worker * UniquePtr<Foo> fooPtr(createFoo()); // NOT fooPtr = createFoo();
251*35238bceSAndroid Build Coastguard Worker *
252*35238bceSAndroid Build Coastguard Worker *//*--------------------------------------------------------------------*/
253*35238bceSAndroid Build Coastguard Worker template <typename T, class Deleter = DefaultDeleter<T>>
254*35238bceSAndroid Build Coastguard Worker class UniquePtr : public UniqueBase<T, Deleter>
255*35238bceSAndroid Build Coastguard Worker {
256*35238bceSAndroid Build Coastguard Worker public:
257*35238bceSAndroid Build Coastguard Worker explicit UniquePtr(T *ptr, Deleter deleter = Deleter());
258*35238bceSAndroid Build Coastguard Worker UniquePtr(PtrData<T, Deleter> data);
259*35238bceSAndroid Build Coastguard Worker MovePtr<T, Deleter> move(void);
260*35238bceSAndroid Build Coastguard Worker
261*35238bceSAndroid Build Coastguard Worker private:
262*35238bceSAndroid Build Coastguard Worker UniquePtr(const UniquePtr<T> &other); // Not allowed!
263*35238bceSAndroid Build Coastguard Worker UniquePtr operator=(const UniquePtr<T> &other); // Not allowed!
264*35238bceSAndroid Build Coastguard Worker };
265*35238bceSAndroid Build Coastguard Worker
266*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
267*35238bceSAndroid Build Coastguard Worker * \brief Construct unique pointer.
268*35238bceSAndroid Build Coastguard Worker * \param ptr Pointer to be managed.
269*35238bceSAndroid Build Coastguard Worker *
270*35238bceSAndroid Build Coastguard Worker * Pointer ownership is transferred to the UniquePtr.
271*35238bceSAndroid Build Coastguard Worker *//*--------------------------------------------------------------------*/
272*35238bceSAndroid Build Coastguard Worker template <typename T, class Deleter>
UniquePtr(T * ptr,Deleter deleter)273*35238bceSAndroid Build Coastguard Worker inline UniquePtr<T, Deleter>::UniquePtr(T *ptr, Deleter deleter) : UniqueBase<T, Deleter>(ptr, deleter)
274*35238bceSAndroid Build Coastguard Worker {
275*35238bceSAndroid Build Coastguard Worker }
276*35238bceSAndroid Build Coastguard Worker
277*35238bceSAndroid Build Coastguard Worker template <typename T, class Deleter>
UniquePtr(PtrData<T,Deleter> data)278*35238bceSAndroid Build Coastguard Worker inline UniquePtr<T, Deleter>::UniquePtr(PtrData<T, Deleter> data) : UniqueBase<T, Deleter>(data)
279*35238bceSAndroid Build Coastguard Worker {
280*35238bceSAndroid Build Coastguard Worker }
281*35238bceSAndroid Build Coastguard Worker
282*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
283*35238bceSAndroid Build Coastguard Worker * \brief Relinquish ownership of pointer.
284*35238bceSAndroid Build Coastguard Worker *
285*35238bceSAndroid Build Coastguard Worker * This method returns a MovePtr that now owns the pointer. The pointer in
286*35238bceSAndroid Build Coastguard Worker * the UniquePtr is set to null.
287*35238bceSAndroid Build Coastguard Worker *//*--------------------------------------------------------------------*/
288*35238bceSAndroid Build Coastguard Worker template <typename T, class Deleter>
move(void)289*35238bceSAndroid Build Coastguard Worker inline MovePtr<T, Deleter> UniquePtr<T, Deleter>::move(void)
290*35238bceSAndroid Build Coastguard Worker {
291*35238bceSAndroid Build Coastguard Worker return MovePtr<T, Deleter>(this->releaseData());
292*35238bceSAndroid Build Coastguard Worker }
293*35238bceSAndroid Build Coastguard Worker
294*35238bceSAndroid Build Coastguard Worker } // namespace details
295*35238bceSAndroid Build Coastguard Worker
296*35238bceSAndroid Build Coastguard Worker using details::MovePtr;
297*35238bceSAndroid Build Coastguard Worker using details::newMovePtr;
298*35238bceSAndroid Build Coastguard Worker using details::UniquePtr;
299*35238bceSAndroid Build Coastguard Worker
300*35238bceSAndroid Build Coastguard Worker } // namespace de
301*35238bceSAndroid Build Coastguard Worker
302*35238bceSAndroid Build Coastguard Worker #endif // _DEUNIQUEPTR_HPP
303