Program Listing for File ptr_wrapper.hpp¶
↰ Return to documentation for file (software/shared/ptr-wrapper/include/ptr_wrapper.hpp)
#pragma once
#include <functional>
#include <stdexcept>
template <typename T>
class PtrWrapper
{
public:
PtrWrapper() = default;
PtrWrapper(T* ptr, std::function<void(T*)> deallocator)
: PtrWrapper([ptr](void)
{ return ptr; }, deallocator)
{
}
PtrWrapper(std::function<T*(void)> allocator, std::function<void(T*)> deallocator)
: _deallocator(deallocator)
{
if (!allocator)
throw std::invalid_argument("Allocator must be provided");
if (!deallocator)
throw std::invalid_argument("Deallocator must be provided");
_ptr = allocator();
}
~PtrWrapper()
{
try
{
if (_ptr)
_deallocator(_ptr);
}
catch (...)
{
// ignore - since we're in a destructor, we can't throw
}
}
// we do NOT want to allow copying, that doesn't make sense.
// Moving is OK though
PtrWrapper(const PtrWrapper&) = delete;
PtrWrapper(PtrWrapper&& other) noexcept
{
swap(*this, other);
}
PtrWrapper& operator=(PtrWrapper) = delete;
PtrWrapper& operator=(PtrWrapper&& other) noexcept
{
swap(*this, other);
return *this;
}
PtrWrapper& operator=(T* ptr)
{
if (_ptr)
_deallocator(_ptr);
_ptr = ptr;
return *this;
}
T** operator&()
{
return &_ptr;
}
friend void swap(PtrWrapper& first, PtrWrapper& second)
{
using std::swap;
swap(first._ptr, second._ptr);
swap(first._deallocator, second._deallocator);
}
// allow all the common methods of getting the file descriptor/"dereferencing"
virtual inline explicit operator T*() const { return get(); }
virtual inline T* operator*() const { return get(); }
virtual inline T* operator->() const { return get(); }
virtual inline T* get() const { return _ptr; }
private:
T* _ptr = nullptr;
std::function<void(T*)> _deallocator = nullptr;
};