123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764 |
- #ifndef __GBLIBCPP_MEMORY__
- #define __GBLIBCPP_MEMORY__
- #include <bits/compressed_pair>
- #include <cstddef>
- #include <new>
- #include <type_traits>
- #include <utility>
- namespace std {
- template <typename T>
- constexpr T* addressof(T& arg) noexcept
- {
- return __builtin_addressof(arg);
- }
- // template <typename T>
- // constexpr enable_if_t<is_function_v<remove_reference_t<T>>, T*>
- // addressof(T& arg) noexcept
- // {
- // return &arg;
- // }
- // template <typename T>
- // constexpr enable_if_t<!is_function_v<remove_reference_t<T>>, T*>
- // addressof(T& arg) noexcept
- // {
- // return reinterpret_cast<T*>(
- // &const_cast<char&>(
- // reinterpret_cast<const volatile char&>(arg)
- // )
- // );
- // }
- template <typename T>
- const T* addressof(const T&&) = delete;
- namespace __helpers {
- template <typename Ptr, typename = void>
- struct pointer_difference_type
- { using type = std::ptrdiff_t; };
- template <typename Ptr>
- struct pointer_difference_type<Ptr,
- std::void_t<typename Ptr::difference_type>>
- { using type = typename Ptr::difference_type; };
- template <typename Ptr>
- using pointer_difference_type_t =
- typename pointer_difference_type<Ptr>::type;
- template <typename Base, typename T>
- struct rebind;
- template <template <typename, typename...> typename Template,
- typename NewType, typename OldType, typename... Args>
- struct rebind<Template<OldType, Args...>, NewType> {
- using type = Template<NewType, Args...>;
- };
- template <typename Ptr, typename T, typename = void>
- struct try_rebind { using type = typename rebind<Ptr, T>::type; };
- template <typename Ptr, typename T>
- struct try_rebind<Ptr, T,
- std::void_t<typename Ptr::template rebind<T>>> {
- using type = typename Ptr::template rebind<T>;
- };
- template <typename Ptr, typename = void>
- struct pointer_element {};
- template <typename Ptr>
- struct pointer_element<Ptr, std::enable_if_t<
- std::is_same_v<void, std::void_t<typename Ptr::element_type>>
- >> { using type = typename Ptr::element_type; };
- template <template <typename, typename...> typename Template,
- typename T, typename... Args>
- struct pointer_element<Template<T, Args...>, void>
- { using type = T; };
- template <typename Ptr, typename = void>
- struct pointer_traits_impl {};
- template <typename Ptr>
- struct pointer_traits_impl<Ptr,
- std::void_t<typename pointer_element<Ptr>::type>> {
- using pointer = Ptr;
- using element_type = typename pointer_element<Ptr>::type;
- using difference_type = pointer_difference_type_t<Ptr>;
- template <typename U>
- using rebind = typename try_rebind<Ptr, U>::type;
- static pointer pointer_to(element_type& ref)
- { return Ptr::pointer_to(ref); }
- };
- template <typename T>
- struct pointer_traits_impl<T*, void> {
- using pointer = T*;
- using element_type = T;
- using difference_type = std::ptrdiff_t;
- template <typename U>
- using rebind = U*;
- static pointer pointer_to(element_type& ref)
- { return std::addressof(ref); }
- };
- } // namespace __helpers
- template <typename Ptr>
- struct pointer_traits : public __helpers::pointer_traits_impl<Ptr> {};
- namespace __helpers {
- template <typename Alloc, typename = void>
- struct allocator_pointer
- { using type = typename Alloc::value_type*; };
- template <typename Alloc>
- struct allocator_pointer<Alloc,
- std::void_t<typename Alloc::pointer>>
- { using type = typename Alloc::pointer; };
- template <typename Alloc>
- using allocator_pointer_t =
- typename allocator_pointer<Alloc>::type;
- template <typename Alloc, typename Pointer, typename = void>
- struct allocator_const_pointer {
- using type = typename std::pointer_traits<Pointer>::template
- rebind<const typename Alloc::value_type>;
- };
- template <typename Alloc, typename Pointer>
- struct allocator_const_pointer<Alloc, Pointer,
- std::void_t<typename Alloc::const_pointer>>
- { using type = typename Alloc::const_pointer; };
- template <typename Alloc, typename Pointer>
- using allocator_const_pointer_t =
- typename allocator_const_pointer<Alloc, Pointer>::type;
- template <typename Alloc, typename Pointer, typename = void>
- struct allocator_void_pointer {
- using type = typename std::pointer_traits<Pointer>::template
- rebind<void>;
- };
- template <typename Alloc, typename Pointer>
- struct allocator_void_pointer<Alloc, Pointer,
- std::void_t<typename Alloc::void_pointer>>
- { using type = typename Alloc::void_pointer; };
- template <typename Alloc, typename Pointer>
- using allocator_void_pointer_t =
- typename allocator_void_pointer<Alloc, Pointer>::type;
- template <typename Alloc, typename Pointer, typename = void>
- struct allocator_const_void_pointer {
- using type = typename std::pointer_traits<Pointer>::template
- rebind<const void>;
- };
- template <typename Alloc, typename Pointer>
- struct allocator_const_void_pointer<Alloc, Pointer,
- std::void_t<typename Alloc::const_void_pointer>>
- { using type = typename Alloc::const_void_pointer; };
- template <typename Alloc, typename Pointer>
- using allocator_const_void_pointer_t =
- typename allocator_const_void_pointer<Alloc, Pointer>::type;
- template <typename Alloc, typename = void>
- struct allocator_difference_type
- { using type = std::ptrdiff_t; };
- template <typename Alloc>
- struct allocator_difference_type<Alloc,
- std::void_t<typename Alloc::difference_type>>
- { using type = typename Alloc::difference_type; };
- template <typename Alloc>
- using allocator_difference_type_t =
- typename allocator_difference_type<Alloc>::type;
- template <typename Alloc, typename = void>
- struct allocator_size_type
- { using type = std::size_t; };
- template <typename Alloc>
- struct allocator_size_type<Alloc,
- std::void_t<typename Alloc::size_type>>
- { using type = typename Alloc::size_type; };
- template <typename Alloc>
- using allocator_size_type_t =
- typename allocator_size_type<Alloc>::type;
- template <typename Alloc, typename = void>
- struct allocator_prop_copy
- { using type = std::false_type; };
- template <typename Alloc>
- struct allocator_prop_copy<Alloc,
- std::void_t<typename Alloc::propagate_on_container_copy_assignment>>
- { using type = typename Alloc::propagate_on_container_copy_assignment; };
- template <typename Alloc>
- using allocator_prop_copy_t =
- typename allocator_prop_copy<Alloc>::type;
- template <typename Alloc, typename = void>
- struct allocator_prop_move
- { using type = std::false_type; };
- template <typename Alloc>
- struct allocator_prop_move<Alloc,
- std::void_t<typename Alloc::propagate_on_container_move_assignment>>
- { using type = typename Alloc::propagate_on_container_move_assignment; };
- template <typename Alloc>
- using allocator_prop_move_t =
- typename allocator_prop_move<Alloc>::type;
- template <typename Alloc, typename = void>
- struct allocator_prop_swap
- { using type = std::false_type; };
- template <typename Alloc>
- struct allocator_prop_swap<Alloc,
- std::void_t<typename Alloc::propagate_on_container_swap>>
- { using type = typename Alloc::propagate_on_container_swap; };
- template <typename Alloc>
- using allocator_prop_swap_t =
- typename allocator_prop_swap<Alloc>::type;
- template <typename Alloc, typename = void>
- struct is_always_equal
- { using type = std::false_type; };
- template <typename Alloc>
- struct is_always_equal<Alloc,
- std::void_t<typename Alloc::is_always_equal>>
- { using type = typename Alloc::is_always_equal; };
- template <typename Alloc>
- using is_always_equal_t =
- typename is_always_equal<Alloc>::type;
- template <typename Alloc, typename = void>
- struct allocator_select_on_copy {
- static constexpr Alloc get(const Alloc& alloc)
- { return alloc; }
- };
- template <typename Alloc>
- struct allocator_select_on_copy<Alloc, std::enable_if_t<
- std::is_same_v<void, std::void_t<decltype(
- std::declval<Alloc>().select_on_container_copy_construction()
- )>> >> {
- static constexpr Alloc get(const Alloc& alloc)
- { return alloc.select_on_container_copy_construction(); }
- };
- template <typename Allocator, typename T, typename = void>
- struct allocator_rebind_type {
- using type = typename rebind<Allocator, T>::type;
- };
- template <typename Allocator, typename T>
- struct allocator_rebind_type<Allocator, T, std::void_t<
- typename Allocator::template rebind<T>::other
- >> {
- using type = typename Allocator::template rebind<T>::other;
- };
- } // namespace __helpers
- template <typename T>
- struct allocator {
- using value_type = T;
- using propagate_on_container_move_assignment = std::true_type;
- constexpr allocator() noexcept = default;
- constexpr allocator(const allocator& other) noexcept = default;
- template <typename U>
- constexpr allocator(const allocator<U>&) noexcept {}
- constexpr ~allocator() = default;
- // throws std::bad_alloc
- [[nodiscard]] constexpr T* allocate(std::size_t n)
- { return static_cast<T*>(::operator new(n * sizeof(T))); }
- // TODO: check allocated size
- constexpr void deallocate(T* ptr, std::size_t)
- { ::operator delete(ptr); }
- };
- template <typename T1, typename T2>
- constexpr bool operator==(const allocator<T1>&, const allocator<T2>&) noexcept
- { return true; }
- template <typename T, typename... Args>
- constexpr std::enable_if_t<std::is_same_v<T*,
- decltype(::new(std::declval<void*>()) T(std::declval<Args>()...))> , T*>
- construct_at(T* p, Args&&... args)
- {
- return ::new (static_cast<void*>(p)) T(std::forward<Args>(args)...);
- }
- template <typename T>
- constexpr void destroy_at(T* p)
- {
- // TODO: destroy array
- p->~T();
- }
- template <typename Allocator>
- struct allocator_traits {
- using allocator_type = Allocator;
- using value_type = typename Allocator::value_type;
- using pointer =
- __helpers::allocator_pointer_t<Allocator>;
- using const_pointer =
- __helpers::allocator_const_pointer_t<Allocator, pointer>;
- using void_pointer =
- __helpers::allocator_void_pointer_t<Allocator, pointer>;
- using const_void_pointer =
- __helpers::allocator_const_void_pointer_t<Allocator, pointer>;
- using difference_type =
- __helpers::allocator_difference_type_t<Allocator>;
- using size_type =
- __helpers::allocator_size_type_t<Allocator>;
- using propagate_on_container_copy_assignment =
- __helpers::allocator_prop_copy_t<Allocator>;
- using propagate_on_container_move_assignment =
- __helpers::allocator_prop_move_t<Allocator>;
- using propagate_on_container_swap =
- __helpers::allocator_prop_swap_t<Allocator>;
- using is_always_equal =
- __helpers::is_always_equal_t<Allocator>;
- template <typename T>
- using rebind_alloc =
- typename __helpers::allocator_rebind_type<Allocator, T>::type;
- [[nodiscard]] static constexpr pointer allocate(Allocator& alloc, size_type n)
- { return alloc.allocate(n); }
- static constexpr void deallocate(Allocator& alloc, pointer p, size_type n)
- { return alloc.deallocate(p, n); }
- template <typename T, typename... Args>
- static constexpr void construct(Allocator&, T* p, Args&&... args)
- { std::construct_at(p, std::forward<Args>(args)...); }
- template <typename T>
- static constexpr void destroy(Allocator&, T* p)
- { std::destroy_at(p); }
- static constexpr Allocator
- select_on_container_copy_construction(const Allocator& alloc)
- { return __helpers::allocator_select_on_copy<Allocator>::get(alloc); }
- };
- // TODO: weak_ptr
- template <typename T>
- class shared_ptr {
- public:
- using element_type = std::remove_extent_t<T>;
- using pointer = element_type*; // TODO: pointer_traits
- using const_pointer = const element_type*;
- using reference = element_type&;
- using const_reference = const element_type&;
- private:
- struct control_block_base {
- std::size_t ref_count;
- std::size_t weak_count;
- pointer ptr;
- constexpr control_block_base(std::size_t ref_count,
- std::size_t weak_count, pointer ptr)
- : ref_count(ref_count)
- , weak_count(weak_count)
- , ptr(ptr)
- {
- }
- virtual constexpr ~control_block_base() = default;
- virtual constexpr void do_delete() = 0;
- // template <typename U, std::enable_if_t<std::is_convertible_v<T*, U*>, bool> = true>
- // constexpr operator typename shared_ptr<U>::control_block_base*() const
- // {
- // return this;
- // }
- };
- template <typename Deleter>
- struct control_block : public virtual control_block_base {
- Deleter deleter;
- virtual constexpr ~control_block() = default;
- template <typename UDeleter>
- constexpr control_block(std::size_t ref_count,
- std::size_t weak_count, pointer ptr, UDeleter&& deleter)
- : control_block_base { ref_count, weak_count, ptr }
- , deleter(std::forward<UDeleter>(deleter))
- {
- }
- virtual constexpr void do_delete() override
- {
- if (this->ptr)
- deleter(this->ptr);
- this->ptr = nullptr;
- }
- };
- struct default_control_block : public virtual control_block_base {
- virtual constexpr ~default_control_block() = default;
- constexpr default_control_block(std::size_t ref_count,
- std::size_t weak_count, pointer ptr)
- : control_block_base { ref_count, weak_count, ptr }
- {
- }
- virtual constexpr void do_delete() override
- {
- if (this->ptr)
- delete this->ptr;
- this->ptr = nullptr;
- }
- };
- control_block_base* cb {};
- pointer ptr {};
- void inc_ref()
- {
- if (cb)
- ++cb->ref_count; // TODO: lock and atomic
- }
- void dec_ref()
- {
- if (cb && --cb->ref_count == 0) {
- cb->do_delete();
- if (cb->weak_count == 0)
- delete cb;
- }
- }
- private:
- template <typename Deleter>
- using rebind_allocator = typename std::allocator_traits<Deleter>::template rebind_alloc<control_block<Deleter>>;
- template <typename U>
- friend class shared_ptr;
- public:
- __GBLIBCPP_CONSTEXPR shared_ptr() noexcept = default;
- __GBLIBCPP_CONSTEXPR shared_ptr(std::nullptr_t) noexcept { }
- template <typename U, enable_if_t<is_convertible_v<U*, T*>, bool> = true>
- __GBLIBCPP_CONSTEXPR explicit shared_ptr(U* p) // TODO: array type
- : cb(new default_control_block { 1, 0, p })
- , ptr(p)
- {
- }
- template <typename U, typename Deleter, enable_if_t<is_convertible_v<U*, T*>, bool> = true>
- __GBLIBCPP_CONSTEXPR explicit shared_ptr(U* p, Deleter d)
- : cb(new control_block<Deleter> { 1, 0, p, d })
- , ptr(p)
- {
- }
- template <typename Deleter>
- __GBLIBCPP_CONSTEXPR explicit shared_ptr(std::nullptr_t, Deleter d)
- : cb(new control_block<Deleter> { 1, 0, nullptr, d })
- {
- }
- template <typename U, typename Deleter, typename Allocator,
- enable_if_t<is_convertible_v<U*, T*>, bool> = true>
- __GBLIBCPP_CONSTEXPR explicit shared_ptr(U* p, Deleter d, Allocator alloc)
- {
- cb = std::allocator_traits<
- rebind_allocator<Deleter>>::allocate(alloc, 1);
- std::allocator_traits<
- rebind_allocator<Deleter>>::construct(alloc, cb, 1, 0, p, d);
- ptr = p;
- }
- template <typename Deleter, typename Allocator>
- __GBLIBCPP_CONSTEXPR explicit shared_ptr(std::nullptr_t, Deleter d, Allocator alloc)
- {
- cb = std::allocator_traits<
- rebind_allocator<Deleter>>::allocate(alloc, 1);
- std::allocator_traits<
- rebind_allocator<Deleter>>::construct(alloc, cb, 1, 0, nullptr, d);
- }
- __GBLIBCPP_CONSTEXPR
- shared_ptr(const shared_ptr& other) noexcept
- : cb(other.cb)
- , ptr(other.ptr)
- {
- inc_ref();
- }
- __GBLIBCPP_CONSTEXPR
- shared_ptr(shared_ptr&& other) noexcept
- : cb(std::exchange(other.cb, nullptr))
- , ptr(std::exchange(other.ptr, nullptr))
- {
- }
- template <typename U, enable_if_t<is_convertible_v<U*, T*>, bool> = true>
- __GBLIBCPP_CONSTEXPR
- shared_ptr(const shared_ptr<U>& other) noexcept
- : cb((control_block_base*)other.cb)
- , ptr((T*)other.ptr)
- {
- inc_ref();
- }
- template <typename U, enable_if_t<is_convertible_v<U*, T*>, bool> = true>
- __GBLIBCPP_CONSTEXPR
- shared_ptr(shared_ptr<U>&& other) noexcept
- : cb((control_block_base*)std::exchange(other.cb, nullptr))
- , ptr((T*)std::exchange(other.ptr, nullptr))
- {
- }
- // TODO: weak_ptr and unique_ptr
- __GBLIBCPP_CONSTEXPR
- ~shared_ptr()
- {
- dec_ref();
- cb = nullptr;
- ptr = nullptr;
- }
- __GBLIBCPP_CONSTEXPR
- shared_ptr& operator=(const shared_ptr& other) noexcept
- {
- shared_ptr { other }.swap(*this);
- return *this;
- }
- template <typename U, enable_if_t<is_convertible_v<U*, T*>, bool> = true>
- __GBLIBCPP_CONSTEXPR shared_ptr& operator=(const shared_ptr<U>& other) noexcept
- {
- shared_ptr { other }.swap(*this);
- return *this;
- }
- __GBLIBCPP_CONSTEXPR
- shared_ptr& operator=(shared_ptr&& other) noexcept
- {
- shared_ptr { move(other) }.swap(*this);
- return *this;
- }
- template <typename U, enable_if_t<is_convertible_v<U*, T*>, bool> = true>
- __GBLIBCPP_CONSTEXPR shared_ptr& operator=(shared_ptr<U>&& other) noexcept
- {
- shared_ptr { move(other) }.swap(*this);
- return *this;
- }
- __GBLIBCPP_CONSTEXPR
- element_type* get() const noexcept
- {
- return cb ? ptr : nullptr;
- }
- __GBLIBCPP_CONSTEXPR
- explicit operator bool() const noexcept
- {
- return get();
- }
- __GBLIBCPP_CONSTEXPR
- T& operator*() const noexcept { return *get(); }
- __GBLIBCPP_CONSTEXPR
- T* operator->() const noexcept { return get(); }
- __GBLIBCPP_CONSTEXPR
- element_type& operator[](std::size_t i) const noexcept { return get()[i]; }
- __GBLIBCPP_CONSTEXPR
- long use_count() const noexcept { return cb ? cb->ref_count : 0; }
- __GBLIBCPP_CONSTEXPR
- bool owner_before(const shared_ptr& other) const noexcept
- {
- return cb < other.cb;
- }
- __GBLIBCPP_CONSTEXPR
- void swap(shared_ptr& other) noexcept
- {
- std::swap(cb, other.cb);
- std::swap(ptr, other.ptr);
- }
- __GBLIBCPP_CONSTEXPR
- void reset() noexcept
- {
- shared_ptr {}.swap(*this);
- }
- template <typename U, enable_if_t<is_convertible_v<U*, T*>, bool> = true>
- __GBLIBCPP_CONSTEXPR void reset(U* p) noexcept
- {
- shared_ptr { p }.swap(*this);
- }
- template <typename U, typename Deleter, enable_if_t<is_convertible_v<U*, T*>, bool> = true>
- __GBLIBCPP_CONSTEXPR void reset(U* p, Deleter d) noexcept
- {
- shared_ptr { p, d }.swap(*this);
- }
- template <typename U, typename Deleter, typename Allocator,
- enable_if_t<is_convertible_v<U*, T*>, bool> = true>
- __GBLIBCPP_CONSTEXPR void reset(U* p, Deleter d, Allocator alloc)
- {
- shared_ptr { p, d, alloc }.swap(*this);
- }
- };
- template <typename T>
- struct default_delete {
- __GBLIBCPP_CONSTEXPR default_delete() noexcept = default;
- template <typename U, std::enable_if_t<std::is_convertible_v<U*, T*>, bool> = true>
- __GBLIBCPP_CONSTEXPR default_delete(const default_delete<U>&) noexcept {}
- __GBLIBCPP_CONSTEXPR void operator()(T* p) const
- {
- delete p;
- }
- };
- template <typename T, typename Deleter = std::default_delete<T>>
- class unique_ptr {
- public:
- using element_type = T;
- using deleter_type = Deleter;
- using pointer = element_type*;
- private:
- impl::compressed_pair<pointer, deleter_type> data;
- public:
- __GBLIBCPP_CONSTEXPR unique_ptr() noexcept: data{impl::default_construct_t{}} { }
- __GBLIBCPP_CONSTEXPR unique_ptr(std::nullptr_t) noexcept: unique_ptr{} { }
- __GBLIBCPP_CONSTEXPR unique_ptr(pointer p) noexcept: data{p, deleter_type{}} { }
- __GBLIBCPP_CONSTEXPR unique_ptr(pointer p, const deleter_type& d) noexcept: data{p, d} { }
- __GBLIBCPP_CONSTEXPR unique_ptr(pointer p, deleter_type&& d) noexcept: data{p, std::move(d)} { }
- __GBLIBCPP_CONSTEXPR unique_ptr(const unique_ptr&) = delete;
- __GBLIBCPP_CONSTEXPR unique_ptr(unique_ptr&& other) noexcept
- : data{std::exchange(other.data.first(), nullptr), std::move(other.data.second())} { }
- template <typename U, typename E, std::enable_if_t<
- !std::is_array_v<U> && std::is_convertible_v<U*, T*>
- && std::is_convertible_v<E, Deleter>, bool> = true>
- __GBLIBCPP_CONSTEXPR unique_ptr(unique_ptr<U, E>&& other) noexcept
- : data{std::exchange(other.data.first(), nullptr), std::move(other.data.second())} { }
- __GBLIBCPP_CONSTEXPR ~unique_ptr() { reset(); }
- __GBLIBCPP_CONSTEXPR unique_ptr& operator=(const unique_ptr&) = delete;
- __GBLIBCPP_CONSTEXPR unique_ptr& operator=(std::nullptr_t) noexcept
- {
- reset();
- return *this;
- }
- __GBLIBCPP_CONSTEXPR unique_ptr& operator=(unique_ptr&& other) noexcept
- {
- reset(other.release());
- get_deleter() = std::move(other.get_deleter());
- return *this;
- }
- template <typename U, typename E, std::enable_if_t<
- !std::is_array_v<U> && std::is_convertible_v<U*, T*>
- && std::is_assignable_v<Deleter&, E&&>, bool> = true>
- __GBLIBCPP_CONSTEXPR unique_ptr& operator=(unique_ptr<U, E>&& other) noexcept
- {
- reset(other.release());
- get_deleter() = std::move(other.get_deleter());
- return *this;
- }
- __GBLIBCPP_CONSTEXPR void swap(unique_ptr& other) noexcept
- {
- std::swap(data, other.data);
- }
- __GBLIBCPP_CONSTEXPR pointer get() const noexcept { return data.first(); }
- __GBLIBCPP_CONSTEXPR deleter_type& get_deleter() noexcept { return data.second(); }
- __GBLIBCPP_CONSTEXPR const deleter_type& get_deleter() const noexcept { return data.second(); }
- __GBLIBCPP_CONSTEXPR pointer release() noexcept
- {
- pointer ret = get();
- data.first() = nullptr;
- return ret;
- }
- __GBLIBCPP_CONSTEXPR void reset(pointer p = pointer{}) noexcept
- {
- pointer old = release();
- data.first() = p;
- if (old)
- get_deleter()(old);
- }
- __GBLIBCPP_CONSTEXPR explicit operator bool() const noexcept { return get(); }
- __GBLIBCPP_CONSTEXPR pointer operator->() const noexcept { return get(); }
- __GBLIBCPP_CONSTEXPR std::add_lvalue_reference_t<T> operator*() const
- noexcept(noexcept(*std::declval<pointer>())) { return *get(); }
- };
- // TODO: use only one allocation
- template <typename T, typename... Args>
- std::shared_ptr<T> make_shared(Args&&... args)
- {
- return std::shared_ptr<T>(new T(std::forward<Args>(args)...));
- }
- template <typename T, typename... Args>
- __GBLIBCPP_CONSTEXPR std::unique_ptr<T> make_unique(Args&&... args)
- {
- return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
- }
- template <typename T>
- __GBLIBCPP_CONSTEXPR void swap(std::shared_ptr<T>& lhs, std::shared_ptr<T>& rhs) noexcept
- {
- lhs.swap(rhs);
- }
- template <typename T, typename D>
- __GBLIBCPP_CONSTEXPR void swap(std::unique_ptr<T, D>& lhs, std::unique_ptr<T, D>& rhs) noexcept
- {
- lhs.swap(rhs);
- }
- } // namespace std
- #endif
|