관리-도구
편집 파일: default_delete.hpp
////////////////////////////////////////////////////////////////////////////// // // (C) Copyright Ion Gaztanaga 2014-2014. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // See http://www.boost.org/libs/move for documentation. // ////////////////////////////////////////////////////////////////////////////// #ifndef BOOST_MOVE_DEFAULT_DELETE_HPP_INCLUDED #define BOOST_MOVE_DEFAULT_DELETE_HPP_INCLUDED #ifndef BOOST_CONFIG_HPP # include <boost/config.hpp> #endif # #if defined(BOOST_HAS_PRAGMA_ONCE) # pragma once #endif #include <boost/move/detail/config_begin.hpp> #include <boost/move/detail/workaround.hpp> #include <boost/move/detail/unique_ptr_meta_utils.hpp> #include <boost/move/utility_core.hpp> #include <cstddef> //For std::size_t,std::nullptr_t //!\file //! Describes the default deleter (destruction policy) of <tt>unique_ptr</tt>: <tt>default_delete</tt>. namespace boost{ // @cond namespace move_upd { namespace bmupmu = ::boost::move_upmu; //////////////////////////////////////// //// enable_def_del //////////////////////////////////////// //compatible with a pointer type T*: //When either Y* is convertible to T* //Y is U[N] and T is U cv [] template<class U, class T> struct def_del_compatible_cond : bmupmu::is_convertible<U*, T*> {}; template<class U, class T, std::size_t N> struct def_del_compatible_cond<U[N], T[]> : def_del_compatible_cond<U[], T[]> {}; template<class U, class T, class Type = bmupmu::nat> struct enable_def_del : bmupmu::enable_if_c<def_del_compatible_cond<U, T>::value, Type> {}; //////////////////////////////////////// //// enable_defdel_call //////////////////////////////////////// //When 2nd is T[N], 1st(*)[N] shall be convertible to T(*)[N]; //When 2nd is T[], 1st(*)[] shall be convertible to T(*)[]; //Otherwise, 1st* shall be convertible to 2nd*. template<class U, class T, class Type = bmupmu::nat> struct enable_defdel_call : public enable_def_del<U, T, Type> {}; template<class U, class T, class Type> struct enable_defdel_call<U, T[], Type> : public enable_def_del<U[], T[], Type> {}; template<class U, class T, class Type, std::size_t N> struct enable_defdel_call<U, T[N], Type> : public enable_def_del<U[N], T[N], Type> {}; //////////////////////////////////////// //// Some bool literal zero conversion utilities //////////////////////////////////////// struct bool_conversion {int for_bool; int for_arg(); }; typedef int bool_conversion::* explicit_bool_arg; #if !defined(BOOST_NO_CXX11_NULLPTR) && !defined(BOOST_NO_CXX11_DECLTYPE) typedef decltype(nullptr) nullptr_type; #elif !defined(BOOST_NO_CXX11_NULLPTR) typedef std::nullptr_t nullptr_type; #else typedef int (bool_conversion::*nullptr_type)(); #endif template<bool B> struct is_array_del {}; template<class T> void call_delete(T *p, is_array_del<true>) { delete [] p; } template<class T> void call_delete(T *p, is_array_del<false>) { delete p; } template< class T, class U , bool enable = def_del_compatible_cond< U, T>::value && !move_upmu::is_array<T>::value && !move_upmu::is_same<typename move_upmu::remove_cv<T>::type, void>::value && !move_upmu::is_same<typename move_upmu::remove_cv<U>::type, typename move_upmu::remove_cv<T>::type>::value > struct missing_virtual_destructor_default_delete { static const bool value = !move_upmu::has_virtual_destructor<T>::value; }; template<class T, class U> struct missing_virtual_destructor_default_delete<T, U, false> { static const bool value = false; }; ////////////////////////////////////// // missing_virtual_destructor ////////////////////////////////////// template<class Deleter, class U> struct missing_virtual_destructor { static const bool value = false; }; template<class T, class U> struct missing_virtual_destructor< ::boost::movelib::default_delete<T>, U > : missing_virtual_destructor_default_delete<T, U> {}; } //namespace move_upd { // @endcond namespace movelib { namespace bmupd = boost::move_upd; namespace bmupmu = ::boost::move_upmu; //!The class template <tt>default_delete</tt> serves as the default deleter //!(destruction policy) for the class template <tt>unique_ptr</tt>. //! //! \tparam T The type to be deleted. It may be an incomplete type template <class T> struct default_delete { //! Default constructor. //! BOOST_CONSTEXPR default_delete() //Avoid "defaulted on its first declaration must not have an exception-specification" error for GCC 4.6 #if !defined(BOOST_GCC) || (BOOST_GCC < 40600 && BOOST_GCC >= 40700) || defined(BOOST_MOVE_DOXYGEN_INVOKED) BOOST_NOEXCEPT #endif #if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) || defined(BOOST_MOVE_DOXYGEN_INVOKED) = default; #else {}; #endif #if defined(BOOST_MOVE_DOXYGEN_INVOKED) //! Trivial copy constructor //! default_delete(const default_delete&) BOOST_NOEXCEPT = default; //! Trivial assignment //! default_delete &operator=(const default_delete&) BOOST_NOEXCEPT = default; #else typedef typename bmupmu::remove_extent<T>::type element_type; #endif //! <b>Effects</b>: Constructs a default_delete object from another <tt>default_delete<U></tt> object. //! //! <b>Remarks</b>: This constructor shall not participate in overload resolution unless: //! - If T is not an array type and U* is implicitly convertible to T*. //! - If T is an array type and U* is a more CV qualified pointer to remove_extent<T>::type. template <class U> default_delete(const default_delete<U>& BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmupd::enable_def_del<U BOOST_MOVE_I T>::type* =0) ) BOOST_NOEXCEPT { //If T is not an array type, U derives from T //and T has no virtual destructor, then you have a problem BOOST_MOVE_STATIC_ASSERT(( !bmupd::missing_virtual_destructor<default_delete, U>::value )); } //! <b>Effects</b>: Constructs a default_delete object from another <tt>default_delete<U></tt> object. //! //! <b>Remarks</b>: This constructor shall not participate in overload resolution unless: //! - If T is not an array type and U* is implicitly convertible to T*. //! - If T is an array type and U* is a more CV qualified pointer to remove_extent<T>::type. template <class U> BOOST_MOVE_DOC1ST(default_delete&, typename bmupd::enable_def_del<U BOOST_MOVE_I T BOOST_MOVE_I default_delete &>::type) operator=(const default_delete<U>&) BOOST_NOEXCEPT { //If T is not an array type, U derives from T //and T has no virtual destructor, then you have a problem BOOST_MOVE_STATIC_ASSERT(( !bmupd::missing_virtual_destructor<default_delete, U>::value )); return *this; } //! <b>Effects</b>: if T is not an array type, calls <tt>delete</tt> on static_cast<T*>(ptr), //! otherwise calls <tt>delete[]</tt> on static_cast<remove_extent<T>::type*>(ptr). //! //! <b>Remarks</b>: If U is an incomplete type, the program is ill-formed. //! This operator shall not participate in overload resolution unless: //! - T is not an array type and U* is convertible to T*, OR //! - T is an array type, and remove_cv<U>::type is the same type as //! remove_cv<remove_extent<T>::type>::type and U* is convertible to remove_extent<T>::type*. template <class U> BOOST_MOVE_DOC1ST(void, typename bmupd::enable_defdel_call<U BOOST_MOVE_I T BOOST_MOVE_I void>::type) operator()(U* ptr) const BOOST_NOEXCEPT { //U must be a complete type BOOST_MOVE_STATIC_ASSERT(sizeof(U) > 0); //If T is not an array type, U derives from T //and T has no virtual destructor, then you have a problem BOOST_MOVE_STATIC_ASSERT(( !bmupd::missing_virtual_destructor<default_delete, U>::value )); element_type * const p = static_cast<element_type*>(ptr); move_upd::call_delete(p, move_upd::is_array_del<bmupmu::is_array<T>::value>()); } //! <b>Effects</b>: Same as <tt>(*this)(static_cast<element_type*>(nullptr))</tt>. //! void operator()(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) const BOOST_NOEXCEPT { BOOST_MOVE_STATIC_ASSERT(sizeof(element_type) > 0); } }; } //namespace movelib { } //namespace boost{ #include <boost/move/detail/config_end.hpp> #endif //#ifndef BOOST_MOVE_DEFAULT_DELETE_HPP_INCLUDED