128 lines
2.6 KiB
C++
128 lines
2.6 KiB
C++
// vi:set ft=cpp: -*- Mode: C++ -*-
|
|
/*
|
|
* Copyright (C) 2013 Technische Universität Dresden.
|
|
* Copyright (C) 2014-2017, 2020, 2023-2024 Kernkonzept GmbH.
|
|
*
|
|
* License: see LICENSE.spdx (in this directory or the directories above)
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "type_traits"
|
|
|
|
namespace cxx
|
|
{
|
|
|
|
template< typename T >
|
|
struct default_delete
|
|
{
|
|
default_delete() {}
|
|
|
|
template< typename U >
|
|
default_delete(default_delete<U> const &) {}
|
|
|
|
void operator () (T *p) const
|
|
{ delete p; }
|
|
};
|
|
|
|
template< typename T >
|
|
struct default_delete<T[]>
|
|
{
|
|
default_delete() {}
|
|
|
|
void operator () (T *p)
|
|
{ delete [] p; }
|
|
};
|
|
|
|
template< typename T, typename C >
|
|
struct unique_ptr_index_op {};
|
|
|
|
template< typename T, typename C >
|
|
struct unique_ptr_index_op<T[], C>
|
|
{
|
|
typedef T &reference;
|
|
reference operator [] (int idx) const
|
|
{ return static_cast<C const *>(this)->get()[idx]; }
|
|
};
|
|
|
|
template< typename T, typename T_Del = default_delete<T> >
|
|
class unique_ptr : public unique_ptr_index_op<T, unique_ptr<T, T_Del> >
|
|
{
|
|
private:
|
|
struct _unspec;
|
|
typedef _unspec* _unspec_ptr_type;
|
|
|
|
public:
|
|
typedef cxx::remove_extent_t<T> element_type;
|
|
typedef element_type *pointer;
|
|
typedef element_type &reference;
|
|
typedef T_Del deleter_type;
|
|
|
|
unique_ptr() : _ptr(pointer()) {}
|
|
|
|
explicit unique_ptr(pointer p) : _ptr(p) {}
|
|
|
|
unique_ptr(unique_ptr &&o) : _ptr(o.release()) {}
|
|
|
|
~unique_ptr() { reset(); }
|
|
|
|
unique_ptr &operator = (unique_ptr &&o)
|
|
{
|
|
reset(o.release());
|
|
return *this;
|
|
}
|
|
|
|
unique_ptr &operator = (_unspec_ptr_type)
|
|
{
|
|
reset();
|
|
return *this;
|
|
}
|
|
|
|
element_type &operator * () const { return *get(); }
|
|
pointer operator -> () const { return get(); }
|
|
|
|
pointer get() const { return _ptr; }
|
|
|
|
operator _unspec_ptr_type () const
|
|
{ return reinterpret_cast<_unspec_ptr_type>(get()); }
|
|
|
|
pointer release()
|
|
{
|
|
pointer r = _ptr;
|
|
_ptr = 0;
|
|
return r;
|
|
}
|
|
|
|
void reset(pointer p = pointer())
|
|
{
|
|
if (p != get())
|
|
{
|
|
deleter_type()(get());
|
|
_ptr = p;
|
|
}
|
|
}
|
|
|
|
unique_ptr(unique_ptr const &) = delete;
|
|
unique_ptr &operator = (unique_ptr const &) = delete;
|
|
|
|
private:
|
|
pointer _ptr;
|
|
};
|
|
|
|
template< typename T >
|
|
unique_ptr<T>
|
|
make_unique_ptr(T *p)
|
|
{ return unique_ptr<T>(p); }
|
|
|
|
template< typename T >
|
|
cxx::enable_if_t<cxx::is_array<T>::value, unique_ptr<T>>
|
|
make_unique(unsigned long size)
|
|
{ return cxx::unique_ptr<T>(new cxx::remove_extent_t<T>[size]()); }
|
|
|
|
template< typename T, typename... Args >
|
|
cxx::enable_if_t<!cxx::is_array<T>::value, unique_ptr<T>>
|
|
make_unique(Args &&... args)
|
|
{ return cxx::unique_ptr<T>(new T(cxx::forward<Args>(args)...)); }
|
|
|
|
}
|