1//////////////////////////////////////////////////////////////////////////////
2//
3// (C) Copyright Ion Gaztanaga 2014-2014. Distributed under the Boost
4// Software License, Version 1.0. (See accompanying file
5// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6//
7// See http://www.boost.org/libs/move for documentation.
8//
9//////////////////////////////////////////////////////////////////////////////
10
11#ifndef BOOST_MOVE_DEFAULT_DELETE_HPP_INCLUDED
12#define BOOST_MOVE_DEFAULT_DELETE_HPP_INCLUDED
13
14#ifndef BOOST_CONFIG_HPP
15# include <boost/config.hpp>
16#endif
17#
18#if defined(BOOST_HAS_PRAGMA_ONCE)
19# pragma once
20#endif
21
22#include <boost/move/detail/config_begin.hpp>
23#include <boost/move/detail/workaround.hpp>
24#include <boost/move/detail/unique_ptr_meta_utils.hpp>
25#include <boost/move/utility_core.hpp>
26#include <boost/static_assert.hpp>
27
28#include <cstddef> //For std::size_t,std::nullptr_t
29
30//!\file
31//! Describes the default deleter (destruction policy) of <tt>unique_ptr</tt>: <tt>default_delete</tt>.
32
33namespace boost{
34// @cond
35namespace move_upd {
36
37namespace bmupmu = ::boost::move_upmu;
38
39////////////////////////////////////////
40//// enable_def_del
41////////////////////////////////////////
42
43//compatible with a pointer type T*:
44//When either Y* is convertible to T*
45//Y is U[N] and T is U cv []
46template<class U, class T>
47struct def_del_compatible_cond
48 : bmupmu::is_convertible<U*, T*>
49{};
50
51template<class U, class T, std::size_t N>
52struct def_del_compatible_cond<U[N], T[]>
53 : def_del_compatible_cond<U[], T[]>
54{};
55
56template<class U, class T, class Type = bmupmu::nat>
57struct enable_def_del
58 : bmupmu::enable_if_c<def_del_compatible_cond<U, T>::value, Type>
59{};
60
61////////////////////////////////////////
62//// enable_defdel_call
63////////////////////////////////////////
64
65//When 2nd is T[N], 1st(*)[N] shall be convertible to T(*)[N];
66//When 2nd is T[], 1st(*)[] shall be convertible to T(*)[];
67//Otherwise, 1st* shall be convertible to 2nd*.
68
69template<class U, class T, class Type = bmupmu::nat>
70struct enable_defdel_call
71 : public enable_def_del<U, T, Type>
72{};
73
74template<class U, class T, class Type>
75struct enable_defdel_call<U, T[], Type>
76 : public enable_def_del<U[], T[], Type>
77{};
78
79template<class U, class T, class Type, std::size_t N>
80struct enable_defdel_call<U, T[N], Type>
81 : public enable_def_del<U[N], T[N], Type>
82{};
83
84////////////////////////////////////////
85//// Some bool literal zero conversion utilities
86////////////////////////////////////////
87
88struct bool_conversion {int for_bool; int for_arg(); };
89typedef int bool_conversion::* explicit_bool_arg;
90
91#if !defined(BOOST_NO_CXX11_NULLPTR) && !defined(BOOST_NO_CXX11_DECLTYPE)
92 typedef decltype(nullptr) nullptr_type;
93#elif !defined(BOOST_NO_CXX11_NULLPTR)
94 typedef std::nullptr_t nullptr_type;
95#else
96 typedef int (bool_conversion::*nullptr_type)();
97#endif
98
99} //namespace move_upd {
100// @endcond
101
102namespace movelib {
103
104namespace bmupd = boost::move_upd;
105namespace bmupmu = ::boost::move_upmu;
106
107//!The class template <tt>default_delete</tt> serves as the default deleter
108//!(destruction policy) for the class template <tt>unique_ptr</tt>.
109//!
110//! \tparam T The type to be deleted. It may be an incomplete type
111template <class T>
112struct default_delete
113{
114 //! Default constructor.
115 //!
116 BOOST_CONSTEXPR default_delete()
117 //Avoid "defaulted on its first declaration must not have an exception-specification" error for GCC 4.6
118 #if !defined(BOOST_GCC) || (BOOST_GCC < 40600 && BOOST_GCC >= 40700) || defined(BOOST_MOVE_DOXYGEN_INVOKED)
119 BOOST_NOEXCEPT
120 #endif
121 #if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) || defined(BOOST_MOVE_DOXYGEN_INVOKED)
122 = default;
123 #else
124 {};
125 #endif
126
127 #if defined(BOOST_MOVE_DOXYGEN_INVOKED)
128 //! Trivial copy constructor
129 //!
130 default_delete(const default_delete&) BOOST_NOEXCEPT = default;
131 //! Trivial assignment
132 //!
133 default_delete &operator=(const default_delete&) BOOST_NOEXCEPT = default;
134 #else
135 typedef typename bmupmu::remove_extent<T>::type element_type;
136 #endif
137
138 //! <b>Effects</b>: Constructs a default_delete object from another <tt>default_delete<U></tt> object.
139 //!
140 //! <b>Remarks</b>: This constructor shall not participate in overload resolution unless:
141 //! - If T is not an array type and U* is implicitly convertible to T*.
142 //! - If T is an array type and U* is a more CV qualified pointer to remove_extent<T>::type.
143 template <class U>
144 default_delete(const default_delete<U>&
145 BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmupd::enable_def_del<U BOOST_MOVE_I T>::type* =0)
146 ) BOOST_NOEXCEPT
147 {
148 //If T is not an array type, U derives from T
149 //and T has no virtual destructor, then you have a problem
150 BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor<default_delete, U>::value ));
151 }
152
153 //! <b>Effects</b>: Constructs a default_delete object from another <tt>default_delete<U></tt> object.
154 //!
155 //! <b>Remarks</b>: This constructor shall not participate in overload resolution unless:
156 //! - If T is not an array type and U* is implicitly convertible to T*.
157 //! - If T is an array type and U* is a more CV qualified pointer to remove_extent<T>::type.
158 template <class U>
159 BOOST_MOVE_DOC1ST(default_delete&,
160 typename bmupd::enable_def_del<U BOOST_MOVE_I T BOOST_MOVE_I default_delete &>::type)
161 operator=(const default_delete<U>&) BOOST_NOEXCEPT
162 {
163 //If T is not an array type, U derives from T
164 //and T has no virtual destructor, then you have a problem
165 BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor<default_delete, U>::value ));
166 return *this;
167 }
168
169 //! <b>Effects</b>: if T is not an array type, calls <tt>delete</tt> on static_cast<T*>(ptr),
170 //! otherwise calls <tt>delete[]</tt> on static_cast<remove_extent<T>::type*>(ptr).
171 //!
172 //! <b>Remarks</b>: If U is an incomplete type, the program is ill-formed.
173 //! This operator shall not participate in overload resolution unless:
174 //! - T is not an array type and U* is convertible to T*, OR
175 //! - T is an array type, and remove_cv<U>::type is the same type as
176 //! remove_cv<remove_extent<T>::type>::type and U* is convertible to remove_extent<T>::type*.
177 template <class U>
178 BOOST_MOVE_DOC1ST(void, typename bmupd::enable_defdel_call<U BOOST_MOVE_I T BOOST_MOVE_I void>::type)
179 operator()(U* ptr) const BOOST_NOEXCEPT
180 {
181 //U must be a complete type
182 BOOST_STATIC_ASSERT(sizeof(U) > 0);
183 //If T is not an array type, U derives from T
184 //and T has no virtual destructor, then you have a problem
185 BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor<default_delete, U>::value ));
186 element_type * const p = static_cast<element_type*>(ptr);
187 bmupmu::is_array<T>::value ? delete [] p : delete p;
188 }
189
190 //! <b>Effects</b>: Same as <tt>(*this)(static_cast<element_type*>(nullptr))</tt>.
191 //!
192 void operator()(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) const BOOST_NOEXCEPT
193 { BOOST_STATIC_ASSERT(sizeof(element_type) > 0); }
194};
195
196} //namespace movelib {
197} //namespace boost{
198
199#include <boost/move/detail/config_end.hpp>
200
201#endif //#ifndef BOOST_MOVE_DEFAULT_DELETE_HPP_INCLUDED
202