File Coverage

/usr/include/c++/5/bits/unique_ptr.h
Criterion Covered Total %
statement 0 10 0.0
branch 0 2 0.0
condition n/a
subroutine n/a
pod n/a
total 0 12 0.0


line stmt bran cond sub pod time code
1             // unique_ptr implementation -*- C++ -*-
2              
3             // Copyright (C) 2008-2015 Free Software Foundation, Inc.
4             //
5             // This file is part of the GNU ISO C++ Library. This library is free
6             // software; you can redistribute it and/or modify it under the
7             // terms of the GNU General Public License as published by the
8             // Free Software Foundation; either version 3, or (at your option)
9             // any later version.
10              
11             // This library is distributed in the hope that it will be useful,
12             // but WITHOUT ANY WARRANTY; without even the implied warranty of
13             // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14             // GNU General Public License for more details.
15              
16             // Under Section 7 of GPL version 3, you are granted additional
17             // permissions described in the GCC Runtime Library Exception, version
18             // 3.1, as published by the Free Software Foundation.
19              
20             // You should have received a copy of the GNU General Public License and
21             // a copy of the GCC Runtime Library Exception along with this program;
22             // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23             // .
24              
25             /** @file bits/unique_ptr.h
26             * This is an internal header file, included by other library headers.
27             * Do not attempt to use it directly. @headername{memory}
28             */
29              
30             #ifndef _UNIQUE_PTR_H
31             #define _UNIQUE_PTR_H 1
32              
33             #include
34             #include
35             #include
36             #include
37             #include
38              
39             namespace std _GLIBCXX_VISIBILITY(default)
40             {
41             _GLIBCXX_BEGIN_NAMESPACE_VERSION
42              
43             /**
44             * @addtogroup pointer_abstractions
45             * @{
46             */
47              
48             #if _GLIBCXX_USE_DEPRECATED
49             template class auto_ptr;
50             #endif
51              
52             /// Primary template of default_delete, used by unique_ptr
53             template
54             struct default_delete
55             {
56             /// Default constructor
57             constexpr default_delete() noexcept = default;
58              
59             /** @brief Converting constructor.
60             *
61             * Allows conversion from a deleter for arrays of another type, @p _Up,
62             * only if @p _Up* is convertible to @p _Tp*.
63             */
64             template
65             enable_if::value>::type>
66             default_delete(const default_delete<_Up>&) noexcept { }
67              
68             /// Calls @c delete @p __ptr
69             void
70 0           operator()(_Tp* __ptr) const
71             {
72             static_assert(!is_void<_Tp>::value,
73             "can't delete pointer to incomplete type");
74             static_assert(sizeof(_Tp)>0,
75             "can't delete pointer to incomplete type");
76 0           delete __ptr;
77 0           }
78             };
79              
80             // _GLIBCXX_RESOLVE_LIB_DEFECTS
81             // DR 740 - omit specialization for array objects with a compile time length
82             /// Specialization for arrays, default_delete.
83             template
84             struct default_delete<_Tp[]>
85             {
86             private:
87             template
88             using __remove_cv = typename remove_cv<_Up>::type;
89              
90             // Like is_base_of<_Tp, _Up> but false if unqualified types are the same
91             template
92             using __is_derived_Tp
93             = __and_< is_base_of<_Tp, _Up>,
94             __not_, __remove_cv<_Up>>> >;
95              
96             public:
97             /// Default constructor
98             constexpr default_delete() noexcept = default;
99              
100             /** @brief Converting constructor.
101             *
102             * Allows conversion from a deleter for arrays of another type, such as
103             * a const-qualified version of @p _Tp.
104             *
105             * Conversions from types derived from @c _Tp are not allowed because
106             * it is unsafe to @c delete[] an array of derived types through a
107             * pointer to the base type.
108             */
109             template
110             enable_if::value>::type>
111             default_delete(const default_delete<_Up[]>&) noexcept { }
112              
113             /// Calls @c delete[] @p __ptr
114             void
115             operator()(_Tp* __ptr) const
116             {
117             static_assert(sizeof(_Tp)>0,
118             "can't delete pointer to incomplete type");
119             delete [] __ptr;
120             }
121              
122             template
123             typename enable_if<__is_derived_Tp<_Up>::value>::type
124             operator()(_Up*) const = delete;
125             };
126              
127             /// 20.7.1.2 unique_ptr for single objects.
128             template >
129             class unique_ptr
130             {
131             // use SFINAE to determine whether _Del::pointer exists
132             class _Pointer
133             {
134             template
135             static typename _Up::pointer __test(typename _Up::pointer*);
136              
137             template
138             static _Tp* __test(...);
139              
140             typedef typename remove_reference<_Dp>::type _Del;
141              
142             public:
143             typedef decltype(__test<_Del>(0)) type;
144             };
145              
146             typedef std::tuple __tuple_type;
147             __tuple_type _M_t;
148              
149             public:
150             typedef typename _Pointer::type pointer;
151             typedef _Tp element_type;
152             typedef _Dp deleter_type;
153              
154             // Constructors.
155              
156             /// Default constructor, creates a unique_ptr that owns nothing.
157             constexpr unique_ptr() noexcept
158             : _M_t()
159             { static_assert(!is_pointer::value,
160             "constructed with null function pointer deleter"); }
161              
162             /** Takes ownership of a pointer.
163             *
164             * @param __p A pointer to an object of @c element_type
165             *
166             * The deleter will be value-initialized.
167             */
168             explicit
169             unique_ptr(pointer __p) noexcept
170             : _M_t(__p, deleter_type())
171             { static_assert(!is_pointer::value,
172             "constructed with null function pointer deleter"); }
173              
174             /** Takes ownership of a pointer.
175             *
176             * @param __p A pointer to an object of @c element_type
177             * @param __d A reference to a deleter.
178             *
179             * The deleter will be initialized with @p __d
180             */
181             unique_ptr(pointer __p,
182             typename conditional::value,
183             deleter_type, const deleter_type&>::type __d) noexcept
184             : _M_t(__p, __d) { }
185              
186             /** Takes ownership of a pointer.
187             *
188             * @param __p A pointer to an object of @c element_type
189             * @param __d An rvalue reference to a deleter.
190             *
191             * The deleter will be initialized with @p std::move(__d)
192             */
193             unique_ptr(pointer __p,
194             typename remove_reference::type&& __d) noexcept
195             : _M_t(std::move(__p), std::move(__d))
196             { static_assert(!std::is_reference::value,
197             "rvalue deleter bound to reference"); }
198              
199             /// Creates a unique_ptr that owns nothing.
200             constexpr unique_ptr(nullptr_t) noexcept : unique_ptr() { }
201              
202             // Move constructors.
203              
204             /// Move constructor.
205             unique_ptr(unique_ptr&& __u) noexcept
206             : _M_t(__u.release(), std::forward(__u.get_deleter())) { }
207              
208             /** @brief Converting constructor from another type
209             *
210             * Requires that the pointer owned by @p __u is convertible to the
211             * type of pointer owned by this object, @p __u does not own an array,
212             * and @p __u has a compatible deleter type.
213             */
214             template
215             is_convertible::pointer, pointer>,
216             __not_>,
217             typename conditional::value,
218             is_same<_Ep, _Dp>,
219             is_convertible<_Ep, _Dp>>::type>>
220             unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept
221             : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter()))
222             { }
223              
224             #if _GLIBCXX_USE_DEPRECATED
225             /// Converting constructor from @c auto_ptr
226             template
227             is_convertible<_Up*, _Tp*>, is_same<_Dp, default_delete<_Tp>>>>
228             unique_ptr(auto_ptr<_Up>&& __u) noexcept;
229             #endif
230              
231             /// Destructor, invokes the deleter if the stored pointer is not null.
232             ~unique_ptr() noexcept
233             {
234             auto& __ptr = std::get<0>(_M_t);
235             if (__ptr != nullptr)
236             get_deleter()(__ptr);
237             __ptr = pointer();
238             }
239              
240             // Assignment.
241              
242             /** @brief Move assignment operator.
243             *
244             * @param __u The object to transfer ownership from.
245             *
246             * Invokes the deleter first if this object owns a pointer.
247             */
248             unique_ptr&
249             operator=(unique_ptr&& __u) noexcept
250             {
251             reset(__u.release());
252             get_deleter() = std::forward(__u.get_deleter());
253             return *this;
254             }
255              
256             /** @brief Assignment from another type.
257             *
258             * @param __u The object to transfer ownership from, which owns a
259             * convertible pointer to a non-array object.
260             *
261             * Invokes the deleter first if this object owns a pointer.
262             */
263             template
264             typename enable_if< __and_<
265             is_convertible::pointer, pointer>,
266             __not_>
267             >::value,
268             unique_ptr&>::type
269             operator=(unique_ptr<_Up, _Ep>&& __u) noexcept
270             {
271             reset(__u.release());
272             get_deleter() = std::forward<_Ep>(__u.get_deleter());
273             return *this;
274             }
275              
276             /// Reset the %unique_ptr to empty, invoking the deleter if necessary.
277             unique_ptr&
278             operator=(nullptr_t) noexcept
279             {
280             reset();
281             return *this;
282             }
283              
284             // Observers.
285              
286             /// Dereference the stored pointer.
287             typename add_lvalue_reference::type
288             operator*() const
289             {
290             _GLIBCXX_DEBUG_ASSERT(get() != pointer());
291             return *get();
292             }
293              
294             /// Return the stored pointer.
295             pointer
296             operator->() const noexcept
297             {
298             _GLIBCXX_DEBUG_ASSERT(get() != pointer());
299             return get();
300             }
301              
302             /// Return the stored pointer.
303             pointer
304             get() const noexcept
305             { return std::get<0>(_M_t); }
306              
307             /// Return a reference to the stored deleter.
308             deleter_type&
309 0           get_deleter() noexcept
310 0           { return std::get<1>(_M_t); }
311              
312             /// Return a reference to the stored deleter.
313             const deleter_type&
314             get_deleter() const noexcept
315             { return std::get<1>(_M_t); }
316              
317             /// Return @c true if the stored pointer is not null.
318             explicit operator bool() const noexcept
319             { return get() == pointer() ? false : true; }
320              
321             // Modifiers.
322              
323             /// Release ownership of any stored pointer.
324             pointer
325             release() noexcept
326             {
327             pointer __p = get();
328             std::get<0>(_M_t) = pointer();
329             return __p;
330             }
331              
332             /** @brief Replace the stored pointer.
333             *
334             * @param __p The new pointer to store.
335             *
336             * The deleter will be invoked if a pointer is already owned.
337             */
338             void
339 0           reset(pointer __p = pointer()) noexcept
340             {
341             using std::swap;
342 0           swap(std::get<0>(_M_t), __p);
343 0 0         if (__p != pointer())
344 0           get_deleter()(__p);
345 0           }
346              
347             /// Exchange the pointer and deleter with another object.
348             void
349             swap(unique_ptr& __u) noexcept
350             {
351             using std::swap;
352             swap(_M_t, __u._M_t);
353             }
354              
355             // Disable copy from lvalue.
356             unique_ptr(const unique_ptr&) = delete;
357             unique_ptr& operator=(const unique_ptr&) = delete;
358             };
359              
360             /// 20.7.1.3 unique_ptr for array objects with a runtime length
361             // [unique.ptr.runtime]
362             // _GLIBCXX_RESOLVE_LIB_DEFECTS
363             // DR 740 - omit specialization for array objects with a compile time length
364             template
365             class unique_ptr<_Tp[], _Dp>
366             {
367             // use SFINAE to determine whether _Del::pointer exists
368             class _Pointer
369             {
370             template
371             static typename _Up::pointer __test(typename _Up::pointer*);
372              
373             template
374             static _Tp* __test(...);
375              
376             typedef typename remove_reference<_Dp>::type _Del;
377              
378             public:
379             typedef decltype(__test<_Del>(0)) type;
380             };
381              
382             typedef std::tuple __tuple_type;
383             __tuple_type _M_t;
384              
385             template
386             using __remove_cv = typename remove_cv<_Up>::type;
387              
388             // like is_base_of<_Tp, _Up> but false if unqualified types are the same
389             template
390             using __is_derived_Tp
391             = __and_< is_base_of<_Tp, _Up>,
392             __not_, __remove_cv<_Up>>> >;
393              
394             template
395             typename _Tp_pointer = typename _Pointer::type,
396             typename _Up_pointer = typename unique_ptr<_Up, _Ep>::pointer>
397             using __safe_conversion = __and_<
398             is_convertible<_Up_pointer, _Tp_pointer>,
399             is_array<_Up>,
400             __or_<__not_>,
401             __not_>,
402             __not_<__is_derived_Tp::type>>
403             >
404             >;
405              
406             public:
407             typedef typename _Pointer::type pointer;
408             typedef _Tp element_type;
409             typedef _Dp deleter_type;
410              
411             // Constructors.
412              
413             /// Default constructor, creates a unique_ptr that owns nothing.
414             constexpr unique_ptr() noexcept
415             : _M_t()
416             { static_assert(!std::is_pointer::value,
417             "constructed with null function pointer deleter"); }
418              
419             /** Takes ownership of a pointer.
420             *
421             * @param __p A pointer to an array of @c element_type
422             *
423             * The deleter will be value-initialized.
424             */
425             explicit
426             unique_ptr(pointer __p) noexcept
427             : _M_t(__p, deleter_type())
428             { static_assert(!is_pointer::value,
429             "constructed with null function pointer deleter"); }
430              
431             // Disable construction from convertible pointer types.
432             template,
433             is_convertible<_Up*, pointer>, __is_derived_Tp<_Up>>>
434             explicit
435             unique_ptr(_Up* __p) = delete;
436              
437             /** Takes ownership of a pointer.
438             *
439             * @param __p A pointer to an array of @c element_type
440             * @param __d A reference to a deleter.
441             *
442             * The deleter will be initialized with @p __d
443             */
444             unique_ptr(pointer __p,
445             typename conditional::value,
446             deleter_type, const deleter_type&>::type __d) noexcept
447             : _M_t(__p, __d) { }
448              
449             /** Takes ownership of a pointer.
450             *
451             * @param __p A pointer to an array of @c element_type
452             * @param __d A reference to a deleter.
453             *
454             * The deleter will be initialized with @p std::move(__d)
455             */
456             unique_ptr(pointer __p, typename
457             remove_reference::type&& __d) noexcept
458             : _M_t(std::move(__p), std::move(__d))
459             { static_assert(!is_reference::value,
460             "rvalue deleter bound to reference"); }
461              
462             /// Move constructor.
463             unique_ptr(unique_ptr&& __u) noexcept
464             : _M_t(__u.release(), std::forward(__u.get_deleter())) { }
465              
466             /// Creates a unique_ptr that owns nothing.
467             constexpr unique_ptr(nullptr_t) noexcept : unique_ptr() { }
468              
469             template
470             typename = _Require<__safe_conversion<_Up, _Ep>,
471             typename conditional::value,
472             is_same<_Ep, _Dp>,
473             is_convertible<_Ep, _Dp>>::type
474             >>
475             unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept
476             : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter()))
477             { }
478              
479             /// Destructor, invokes the deleter if the stored pointer is not null.
480             ~unique_ptr()
481             {
482             auto& __ptr = std::get<0>(_M_t);
483             if (__ptr != nullptr)
484             get_deleter()(__ptr);
485             __ptr = pointer();
486             }
487              
488             // Assignment.
489              
490             /** @brief Move assignment operator.
491             *
492             * @param __u The object to transfer ownership from.
493             *
494             * Invokes the deleter first if this object owns a pointer.
495             */
496             unique_ptr&
497             operator=(unique_ptr&& __u) noexcept
498             {
499             reset(__u.release());
500             get_deleter() = std::forward(__u.get_deleter());
501             return *this;
502             }
503              
504             /** @brief Assignment from another type.
505             *
506             * @param __u The object to transfer ownership from, which owns a
507             * convertible pointer to an array object.
508             *
509             * Invokes the deleter first if this object owns a pointer.
510             */
511             template
512             typename
513             enable_if<__safe_conversion<_Up, _Ep>::value, unique_ptr&>::type
514             operator=(unique_ptr<_Up, _Ep>&& __u) noexcept
515             {
516             reset(__u.release());
517             get_deleter() = std::forward<_Ep>(__u.get_deleter());
518             return *this;
519             }
520              
521             /// Reset the %unique_ptr to empty, invoking the deleter if necessary.
522             unique_ptr&
523             operator=(nullptr_t) noexcept
524             {
525             reset();
526             return *this;
527             }
528              
529             // Observers.
530              
531             /// Access an element of owned array.
532             typename std::add_lvalue_reference::type
533             operator[](size_t __i) const
534             {
535             _GLIBCXX_DEBUG_ASSERT(get() != pointer());
536             return get()[__i];
537             }
538              
539             /// Return the stored pointer.
540             pointer
541             get() const noexcept
542             { return std::get<0>(_M_t); }
543              
544             /// Return a reference to the stored deleter.
545             deleter_type&
546             get_deleter() noexcept
547             { return std::get<1>(_M_t); }
548              
549             /// Return a reference to the stored deleter.
550             const deleter_type&
551             get_deleter() const noexcept
552             { return std::get<1>(_M_t); }
553              
554             /// Return @c true if the stored pointer is not null.
555             explicit operator bool() const noexcept
556             { return get() == pointer() ? false : true; }
557              
558             // Modifiers.
559              
560             /// Release ownership of any stored pointer.
561             pointer
562             release() noexcept
563             {
564             pointer __p = get();
565             std::get<0>(_M_t) = pointer();
566             return __p;
567             }
568              
569             /** @brief Replace the stored pointer.
570             *
571             * @param __p The new pointer to store.
572             *
573             * The deleter will be invoked if a pointer is already owned.
574             */
575             void
576             reset(pointer __p = pointer()) noexcept
577             {
578             using std::swap;
579             swap(std::get<0>(_M_t), __p);
580             if (__p != nullptr)
581             get_deleter()(__p);
582             }
583              
584             // Disable resetting from convertible pointer types.
585             template,
586             is_convertible<_Up*, pointer>, __is_derived_Tp<_Up>>>
587             void reset(_Up*) = delete;
588              
589             /// Exchange the pointer and deleter with another object.
590             void
591             swap(unique_ptr& __u) noexcept
592             {
593             using std::swap;
594             swap(_M_t, __u._M_t);
595             }
596              
597             // Disable copy from lvalue.
598             unique_ptr(const unique_ptr&) = delete;
599             unique_ptr& operator=(const unique_ptr&) = delete;
600              
601             // Disable construction from convertible pointer types.
602             template,
603             is_convertible<_Up*, pointer>, __is_derived_Tp<_Up>>>
604             unique_ptr(_Up*, typename
605             conditional::value,
606             deleter_type, const deleter_type&>::type) = delete;
607              
608             // Disable construction from convertible pointer types.
609             template,
610             is_convertible<_Up*, pointer>, __is_derived_Tp<_Up>>>
611             unique_ptr(_Up*, typename
612             remove_reference::type&&) = delete;
613             };
614              
615             template
616             inline void
617             swap(unique_ptr<_Tp, _Dp>& __x,
618             unique_ptr<_Tp, _Dp>& __y) noexcept
619             { __x.swap(__y); }
620              
621             template
622             typename _Up, typename _Ep>
623             inline bool
624             operator==(const unique_ptr<_Tp, _Dp>& __x,
625             const unique_ptr<_Up, _Ep>& __y)
626             { return __x.get() == __y.get(); }
627              
628             template
629             inline bool
630             operator==(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept
631             { return !__x; }
632              
633             template
634             inline bool
635             operator==(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept
636             { return !__x; }
637              
638             template
639             typename _Up, typename _Ep>
640             inline bool
641             operator!=(const unique_ptr<_Tp, _Dp>& __x,
642             const unique_ptr<_Up, _Ep>& __y)
643             { return __x.get() != __y.get(); }
644              
645             template
646             inline bool
647             operator!=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept
648             { return (bool)__x; }
649              
650             template
651             inline bool
652             operator!=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept
653             { return (bool)__x; }
654              
655             template
656             typename _Up, typename _Ep>
657             inline bool
658             operator<(const unique_ptr<_Tp, _Dp>& __x,
659             const unique_ptr<_Up, _Ep>& __y)
660             {
661             typedef typename
662             std::common_type::pointer,
663             typename unique_ptr<_Up, _Ep>::pointer>::type _CT;
664             return std::less<_CT>()(__x.get(), __y.get());
665             }
666              
667             template
668             inline bool
669             operator<(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
670             { return std::less::pointer>()(__x.get(),
671             nullptr); }
672              
673             template
674             inline bool
675             operator<(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
676             { return std::less::pointer>()(nullptr,
677             __x.get()); }
678              
679             template
680             typename _Up, typename _Ep>
681             inline bool
682             operator<=(const unique_ptr<_Tp, _Dp>& __x,
683             const unique_ptr<_Up, _Ep>& __y)
684             { return !(__y < __x); }
685              
686             template
687             inline bool
688             operator<=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
689             { return !(nullptr < __x); }
690              
691             template
692             inline bool
693             operator<=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
694             { return !(__x < nullptr); }
695              
696             template
697             typename _Up, typename _Ep>
698             inline bool
699             operator>(const unique_ptr<_Tp, _Dp>& __x,
700             const unique_ptr<_Up, _Ep>& __y)
701             { return (__y < __x); }
702              
703             template
704             inline bool
705             operator>(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
706             { return std::less::pointer>()(nullptr,
707             __x.get()); }
708              
709             template
710             inline bool
711             operator>(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
712             { return std::less::pointer>()(__x.get(),
713             nullptr); }
714              
715             template
716             typename _Up, typename _Ep>
717             inline bool
718             operator>=(const unique_ptr<_Tp, _Dp>& __x,
719             const unique_ptr<_Up, _Ep>& __y)
720             { return !(__x < __y); }
721              
722             template
723             inline bool
724             operator>=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
725             { return !(__x < nullptr); }
726              
727             template
728             inline bool
729             operator>=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
730             { return !(nullptr < __x); }
731              
732             /// std::hash specialization for unique_ptr.
733             template
734             struct hash>
735             : public __hash_base>
736             {
737             size_t
738             operator()(const unique_ptr<_Tp, _Dp>& __u) const noexcept
739             {
740             typedef unique_ptr<_Tp, _Dp> _UP;
741             return std::hash()(__u.get());
742             }
743             };
744              
745             #if __cplusplus > 201103L
746              
747             #define __cpp_lib_make_unique 201304
748              
749             template
750             struct _MakeUniq
751             { typedef unique_ptr<_Tp> __single_object; };
752              
753             template
754             struct _MakeUniq<_Tp[]>
755             { typedef unique_ptr<_Tp[]> __array; };
756              
757             template
758             struct _MakeUniq<_Tp[_Bound]>
759             { struct __invalid_type { }; };
760              
761             /// std::make_unique for single objects
762             template
763             inline typename _MakeUniq<_Tp>::__single_object
764             make_unique(_Args&&... __args)
765             { return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); }
766              
767             /// std::make_unique for arrays of unknown bound
768             template
769             inline typename _MakeUniq<_Tp>::__array
770             make_unique(size_t __num)
771             { return unique_ptr<_Tp>(new remove_extent_t<_Tp>[__num]()); }
772              
773             /// Disable std::make_unique for arrays of known bound
774             template
775             inline typename _MakeUniq<_Tp>::__invalid_type
776             make_unique(_Args&&...) = delete;
777             #endif
778              
779             // @} group pointer_abstractions
780              
781             _GLIBCXX_END_NAMESPACE_VERSION
782             } // namespace
783              
784             #endif /* _UNIQUE_PTR_H */