100 lines
2.9 KiB
C++
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;
|
|
};
|
|
} |