libcruft-util/memory/deleter.hpp

100 lines
2.9 KiB
C++

/*
* 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 <danny@nerdcruft.net>
*/
#pragma once
#include <functional>
#include <memory>
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 <typename ValueT>
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<KLASS>::operator() (KLASS *ptr) const \
{ delete ptr; }
///////////////////////////////////////////////////////////////////////////
/// A convenience typedef for a unique_ptr that uses a deferred_delete
/// deleter object.
template <typename ValueT>
using deferred_unique = std::unique_ptr<ValueT, deferred_delete<ValueT>>;
///------------------------------------------------------------------------
/// A convenience function for creation of deferred_unique objects
/// analogous to std::make_unique
template <typename ValueT, typename ...ArgsT>
deferred_unique<ValueT>
make_deferred_unique (ArgsT &&...args)
{
return deferred_unique<ValueT> (
new ValueT (
std::forward<ArgsT> (args)...
)
);
}
///////////////////////////////////////////////////////////////////////////
template <typename T>
class func_deleter {
public:
using func_t = std::function<void(T*)>;
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;
};
}