/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * Copyright 2015-2021 Danny Robson */ #pragma once #include #include namespace cruft::memory { /////////////////////////////////////////////////////////////////////////// /// A deleter object that is deliberately left undefined. /// /// This allows it to be used in places where the definition of `ValueT` /// would otherwise be required (eg, std::unique_ptr). This requires that /// the body be explicitly defined by the user; see `DEFERRED_DELETE`. template struct deferred_delete { void operator() (ValueT*) const; }; ///------------------------------------------------------------------------ /// An implementation of deferred delete that just calls `delete` directly. #define DEFERRED_DELETE(KLASS) \ template <> \ void \ ::cruft::memory::deferred_delete::operator() (KLASS *ptr) const \ { delete ptr; } /////////////////////////////////////////////////////////////////////////// /// A convenience typedef for a unique_ptr that uses a deferred_delete /// deleter object. template using deferred_unique = std::unique_ptr>; ///------------------------------------------------------------------------ /// A convenience function for creation of deferred_unique objects /// analogous to std::make_unique template deferred_unique make_deferred_unique (ArgsT &&...args) { return deferred_unique ( new ValueT ( std::forward (args)... ) ); } /////////////////////////////////////////////////////////////////////////// template class func_deleter { public: using func_t = std::function; explicit func_deleter (func_t _func): m_func (_func) { ; } inline void operator() (T *t) { m_func (t); } private: func_t m_func; }; // dispatch object deletion to a known member function. // // XXX: Generates a "sorry, unimplemented" under GCC (which is // effectively an ICE). Their bug tracker seems to indicate they don't // give a fuck, so we can't use this except under clang. template < typename ValueT, typename OwnerT, void (OwnerT::*Func)(ValueT*) > class owner_deleter { public: owner_deleter (OwnerT &owner): m_owner (owner) { ; } inline void operator() (ValueT *t) { (m_owner.*Func) (t); } private: OwnerT& m_owner; }; }