HelenOS sources
This source file includes following definitions.
- get
- get_deleter
- get_deleter
- release
- reset
- swap
- get
- get_deleter
- get_deleter
- release
- reset
- reset
- swap
- make_unique
- make_unique
- swap
#ifndef LIBCPP_BITS_MEMORY_UNIQUE_PTR
#define LIBCPP_BITS_MEMORY_UNIQUE_PTR
#include <__bits/aux.hpp>
#include <__bits/functional/hash.hpp>
#include <type_traits>
#include <utility>
namespace std
{
template<class T>
struct default_delete
{
default_delete() noexcept = default;
template<class U, class = enable_if_t<is_convertible_v<U*, T*>, void>>
default_delete(const default_delete<U>&) noexcept
{ }
template<class U>
void operator()(U* ptr)
{
delete ptr;
}
};
template<class T>
struct default_delete<T[]>
{
default_delete() noexcept = default;
template<class U, class = enable_if_t<is_convertible_v<U(*)[], T(*)[]>, void>>
default_delete(const default_delete<U[]>&) noexcept
{ }
template<class U, class = enable_if_t<is_convertible_v<U(*)[], T(*)[]>, void>>
void operator()(U* ptr)
{
delete[] ptr;
}
};
template<class T, class D = default_delete<T>>
class unique_ptr;
namespace aux
{
template<class P, class D, class = void>
struct get_unique_pointer: type_is<typename P::element_type*>
{ };
template<class P, class D>
struct get_unique_pointer<P, D, void_t<typename remove_reference_t<D>::pointer>>
: type_is<typename remove_reference_t<D>::pointer>
{ };
}
template<class T, class D>
class unique_ptr
{
public:
using element_type = T;
using deleter_type = D;
using pointer = typename aux::get_unique_pointer<unique_ptr<T, D>, D>::type;
constexpr unique_ptr() noexcept
: ptr_{}, deleter_{}
{ }
explicit unique_ptr(pointer ptr) noexcept
: ptr_{ptr}, deleter_{}
{ }
unique_ptr(pointer ptr, int d) noexcept;
unique_ptr(pointer ptr, char d) noexcept;
unique_ptr(unique_ptr&& other)
: ptr_{move(other.ptr_)}, deleter_{forward<deleter_type>(other.deleter_)}
{
other.ptr_ = nullptr;
}
constexpr unique_ptr(nullptr_t)
: unique_ptr{}
{ }
template<
class U, class E,
class = enable_if_t<
is_convertible_v<
typename unique_ptr<U, E>::pointer,
pointer
>, void
>
>
unique_ptr(unique_ptr<U, E>&& other) noexcept
: ptr_{move(other.ptr_)}, deleter_{forward<D>(other.deleter_)}
{
other.ptr_ = nullptr;
}
~unique_ptr()
{
if (ptr_)
deleter_(ptr_);
}
unique_ptr& operator=(unique_ptr&& rhs) noexcept
{
reset(rhs.release());
deleter_ = forward<deleter_type>(rhs.get_deleter());
return *this;
}
template<
class U, class E,
class = enable_if_t<
is_convertible_v<
typename unique_ptr<U, E>::pointer,
pointer
> && !is_array_v<U>, void
>
>
unique_ptr& operator=(unique_ptr<U, E>&& rhs) noexcept
{
reset(rhs.release());
deleter_ = forward<E>(rhs.get_deleter());
return *this;
}
unique_ptr& operator=(nullptr_t) noexcept
{
reset();
return *this;
}
add_lvalue_reference_t<element_type> operator*() const
{
return *ptr_;
}
pointer operator->() const noexcept
{
return ptr_;
}
pointer get() const noexcept
{
return ptr_;
}
deleter_type& get_deleter() noexcept
{
return deleter_;
}
const deleter_type& get_deleter() const noexcept
{
return deleter_;
}
explicit operator bool() const noexcept
{
return ptr_ != nullptr;
}
pointer release() noexcept
{
auto ret = ptr_;
ptr_ = nullptr;
return ret;
}
void reset(pointer ptr = pointer{}) noexcept
{
auto old = ptr_;
ptr_ = ptr;
if (old)
deleter_(old);
}
void swap(unique_ptr& other) noexcept
{
std::swap(ptr_, other.ptr_);
std::swap(deleter_, other.deleter_);
}
unique_ptr(const unique_ptr&) = delete;
unique_ptr& operator=(const unique_ptr&) = delete;
private:
pointer ptr_;
deleter_type deleter_;
};
namespace aux
{
template<class From, class To>
struct is_convertible_array: is_convertible<From(*)[], To(*)[]>
{ };
template<class From, class To>
inline constexpr bool is_convertible_array_v = is_convertible_array<From, To>::value;
template<class T, class D, class U, class E>
struct compatible_ptrs: integral_constant<
bool,
is_array_v<U> && is_same_v<
typename unique_ptr<T, D>::pointer,
typename unique_ptr<T, D>::element_type*
> && is_same_v<
typename unique_ptr<U, E>::pointer,
typename unique_ptr<U, E>::element_type*
> && is_convertible_array_v<
typename unique_ptr<T, D>::element_type,
typename unique_ptr<U, E>::element_type
> && ((is_reference_v<D> && is_same_v<D, E>) ||
(!is_reference_v<D> && is_convertible_v<E, D>))
>
{ };
template<class T, class D, class U, class E>
inline constexpr bool compatible_ptrs_v = compatible_ptrs<T, D, U, E>::value;
}
template<class T, class D>
class unique_ptr<T[], D>
{
public:
using element_type = T;
using deleter_type = D;
using pointer = typename aux::get_unique_pointer<unique_ptr<T[], D>, D>::type;
constexpr unique_ptr() noexcept
: ptr_{}, deleter_{}
{ }
template<
class U,
class = enable_if_t<
is_same_v<U, T> || aux::is_convertible_array_v<U, T>, void
>
>
explicit unique_ptr(U ptr) noexcept
: ptr_{ptr}, deleter_{}
{ }
template<
class U, class E,
class = enable_if_t<aux::compatible_ptrs_v<T, D, U, E>, void>
>
unique_ptr(U ptr, int d) noexcept;
template<
class U, class E,
class = enable_if_t<aux::compatible_ptrs_v<T, D, U, E>, void>
>
unique_ptr(U ptr, char d) noexcept;
unique_ptr(unique_ptr&& other) noexcept
: ptr_{move(other.ptr_)}, deleter_{forward<deleter_type>(other.deleter_)}
{
other.ptr_ = nullptr;
}
template<
class U, class E,
class = enable_if_t<
is_same_v<U, pointer> ||
(is_same_v<pointer, element_type*> && is_pointer_v<U> &&
aux::is_convertible_array_v<remove_pointer_t<U>, element_type>),
void
>
>
unique_ptr(unique_ptr<U, E>&& other) noexcept
: ptr_{move(other.ptr_)}, deleter_{forward<D>(other.deleter_)}
{
other.ptr_ = nullptr;
}
constexpr unique_ptr(nullptr_t) noexcept
: unique_ptr{}
{ }
~unique_ptr()
{
if (ptr_)
deleter_(ptr_);
}
unique_ptr& operator=(unique_ptr&& rhs) noexcept
{
reset(rhs.release());
deleter_ = forward<deleter_type>(rhs.get_deleter());
return *this;
}
template<
class U, class E,
class = enable_if_t<aux::compatible_ptrs_v<T, D, U, E>, void>
>
unique_ptr& operator=(unique_ptr<U, E>&& rhs) noexcept
{
reset(rhs.release());
deleter_ = forward<E>(rhs.get_deleter());
return *this;
}
unique_ptr& operator=(nullptr_t) noexcept
{
reset();
return *this;
}
element_type& operator[](size_t idx) const
{
return ptr_[idx];
}
pointer get() const noexcept
{
return ptr_;
}
deleter_type& get_deleter() noexcept
{
return deleter_;
}
const deleter_type& get_deleter() const noexcept
{
return deleter_;
}
explicit operator bool() const noexcept
{
return ptr_ != nullptr;
}
pointer release() noexcept
{
auto ret = ptr_;
ptr_ = nullptr;
return ret;
}
template<
class U,
class = enable_if_t<
is_same_v<U, pointer> ||
(is_same_v<pointer, element_type*> && is_pointer_v<U> &&
aux::is_convertible_array_v<remove_pointer_t<U>, element_type>),
void
>
>
void reset(U ptr) noexcept
{
auto old = ptr_;
ptr_ = ptr;
if (old)
deleter_(old);
}
void reset(nullptr_t = nullptr) noexcept
{
reset(pointer{});
}
void swap(unique_ptr& other) noexcept
{
std::swap(ptr_, other.ptr_);
std::swap(deleter_, other.deleter_);
}
unique_ptr(const unique_ptr&) = delete;
unique_ptr& operator=(const unique_ptr&) = delete;
private:
pointer ptr_;
deleter_type deleter_;
};
namespace aux
{
template<class T>
struct is_unbound_array: false_type
{ };
template<class T>
struct is_unbound_array<T[]>: true_type
{ };
template<class T>
struct is_bound_array: false_type
{ };
template<class T, size_t N>
struct is_bound_array<T[N]>: true_type
{ };
}
template<
class T, class... Args,
class = enable_if_t<!is_array_v<T>, void>
>
unique_ptr<T> make_unique(Args&&... args)
{
return unique_ptr<T>(new T(forward<Args>(args)...));
}
template<
class T, class = enable_if_t<aux::is_unbound_array<T>::value, void>
>
unique_ptr<T> make_unique(size_t n)
{
return unique_ptr<T>(new remove_extent_t<T>[n]());
}
template<
class T, class... Args,
class = enable_if_t<aux::is_bound_array<T>::value, void>
>
void make_unique(Args&&...) = delete;
template<class T, class D>
void swap(unique_ptr<T, D>& lhs, unique_ptr<T, D>& rhs) noexcept
{
lhs.swap(rhs);
}
template<class T1, class D1, class T2, class D2>
bool operator==(const unique_ptr<T1, D1>& lhs,
const unique_ptr<T2, D2>& rhs)
{
return lhs.get() == rhs.get();
}
template<class T1, class D1, class T2, class D2>
bool operator!=(const unique_ptr<T1, D1>& lhs,
const unique_ptr<T2, D2>& rhs)
{
return lhs.get() != rhs.get();
}
template<class T1, class D1, class T2, class D2>
bool operator<(const unique_ptr<T1, D1>& lhs,
const unique_ptr<T2, D2>& rhs)
{
return lhs.get() < rhs.get();
}
template<class T1, class D1, class T2, class D2>
bool operator<=(const unique_ptr<T1, D1>& lhs,
const unique_ptr<T2, D2>& rhs)
{
return !(rhs < lhs);
}
template<class T1, class D1, class T2, class D2>
bool operator>(const unique_ptr<T1, D1>& lhs,
const unique_ptr<T2, D2>& rhs)
{
return rhs < lhs;
}
template<class T1, class D1, class T2, class D2>
bool operator>=(const unique_ptr<T1, D1>& lhs,
const unique_ptr<T2, D2>& rhs)
{
return !(lhs < rhs);
}
template<class T, class D>
bool operator==(const unique_ptr<T, D>& ptr, nullptr_t) noexcept
{
return !ptr;
}
template<class T, class D>
bool operator==(nullptr_t, const unique_ptr<T, D>& ptr) noexcept
{
return !ptr;
}
template<class T, class D>
bool operator!=(const unique_ptr<T, D>& ptr, nullptr_t) noexcept
{
return static_cast<bool>(ptr);
}
template<class T, class D>
bool operator!=(nullptr_t, const unique_ptr<T, D>& ptr) noexcept
{
return static_cast<bool>(ptr);
}
template<class T, class D>
bool operator<(const unique_ptr<T, D>& ptr, nullptr_t)
{
return ptr.get() < nullptr;
}
template<class T, class D>
bool operator<(nullptr_t, const unique_ptr<T, D>& ptr)
{
return nullptr < ptr.get();
}
template<class T, class D>
bool operator<=(const unique_ptr<T, D>& ptr, nullptr_t)
{
return !(nullptr < ptr);
}
template<class T, class D>
bool operator<=(nullptr_t, const unique_ptr<T, D>& ptr)
{
return !(ptr < nullptr);
}
template<class T, class D>
bool operator>(const unique_ptr<T, D>& ptr, nullptr_t)
{
return nullptr < ptr;
}
template<class T, class D>
bool operator>(nullptr_t, const unique_ptr<T, D>& ptr)
{
return ptr < nullptr;
}
template<class T, class D>
bool operator>=(const unique_ptr<T, D>& ptr, nullptr_t)
{
return !(ptr < nullptr);
}
template<class T, class D>
bool operator>=(nullptr_t, const unique_ptr<T, D>& ptr)
{
return !(nullptr < ptr);
}
template<class T, class D>
struct hash<unique_ptr<T, D>>
{
size_t operator()(const unique_ptr<T, D>& ptr) const noexcept
{
return hash<typename unique_ptr<T, D>::pointer>{}(ptr.get());
}
using argument_type = unique_ptr<T, D>;
using result_type = size_t;
};
}
#endif
HelenOS homepage, sources at GitHub