| template<class T> | template<class T> | ||||
| constexpr auto is_nothrow_swappable_v = std::is_nothrow_move_constructible<T>::value | |||||
| && std::is_nothrow_move_assignable<T>::value; | |||||
| constexpr auto is_nothrow_swappable_v = std::is_nothrow_move_constructible_v<T> | |||||
| && std::is_nothrow_move_assignable_v<T>; | |||||
| template<class T, class U = std::conditional_t<std::is_nothrow_move_constructible<T>::value, T&&, const T&>> | |||||
| template<class T, class U = std::conditional_t<std::is_nothrow_move_constructible_v<T>, T&&, const T&>> | |||||
| constexpr U forward_if_nothrow_move_constructible(T&& value) noexcept | constexpr U forward_if_nothrow_move_constructible(T&& value) noexcept | ||||
| { | { | ||||
| return std::forward<T>(value); | return std::forward<T>(value); | ||||
| public: | public: | ||||
| template<class RR, class DD, | template<class RR, class DD, | ||||
| std::enable_if_t<(std::is_copy_constructible<R>::value || std::is_nothrow_move_constructible<R>::value) | |||||
| && (std::is_copy_constructible<D>::value || std::is_nothrow_move_constructible<D>::value), int> = 0, | |||||
| std::enable_if_t<(std::is_copy_constructible_v<R> || std::is_nothrow_move_constructible_v<R>) | |||||
| && (std::is_copy_constructible_v<D> || std::is_nothrow_move_constructible_v<D>), int> = 0, | |||||
| std::enable_if_t<detail::is_nothrow_move_or_copy_constructible_from_v<R, RR>, int> = 0, | std::enable_if_t<detail::is_nothrow_move_or_copy_constructible_from_v<R, RR>, int> = 0, | ||||
| std::enable_if_t<detail::is_nothrow_move_or_copy_constructible_from_v<D, DD>, int> = 0 | std::enable_if_t<detail::is_nothrow_move_or_copy_constructible_from_v<D, DD>, int> = 0 | ||||
| > | > | ||||
| explicit unique_resource(RR&& r, DD&& d) noexcept(std::is_nothrow_constructible<R, RR>::value | |||||
| && std::is_nothrow_constructible<D, DD>::value) | |||||
| explicit unique_resource(RR&& r, DD&& d) noexcept(std::is_nothrow_constructible_v<R, RR> | |||||
| && std::is_nothrow_constructible_v<D, DD>) | |||||
| : m_resource(std::forward<RR>(r), make_scope_exit([&r, &d] { d(r); })), | : m_resource(std::forward<RR>(r), make_scope_exit([&r, &d] { d(r); })), | ||||
| m_deleter(std::forward<DD>(d), make_scope_exit([this, &d] { d(get()); })), | m_deleter(std::forward<DD>(d), make_scope_exit([this, &d] { d(get()); })), | ||||
| m_execute_on_destruction(true) | m_execute_on_destruction(true) | ||||
| { | { | ||||
| } | } | ||||
| unique_resource(unique_resource&& other) noexcept(std::is_nothrow_move_constructible<R>::value | |||||
| && std::is_nothrow_move_constructible<D>::value) | |||||
| unique_resource(unique_resource&& other) noexcept(std::is_nothrow_move_constructible_v<R> | |||||
| && std::is_nothrow_move_constructible_v<D>) | |||||
| : m_resource(detail::forward_if_nothrow_move_constructible(other.m_resource.get()), make_scope_exit([] { })), | : m_resource(detail::forward_if_nothrow_move_constructible(other.m_resource.get()), make_scope_exit([] { })), | ||||
| m_deleter(detail::forward_if_nothrow_move_constructible(other.m_deleter.get()), | m_deleter(detail::forward_if_nothrow_move_constructible(other.m_deleter.get()), | ||||
| make_scope_exit([&other] { | make_scope_exit([&other] { | ||||
| } | } | ||||
| template<class RR = R, | template<class RR = R, | ||||
| std::enable_if_t<std::is_pointer<RR>::value | |||||
| && ( std::is_class<std::remove_pointer_t<RR>>::value | |||||
| || std::is_union<std::remove_pointer_t<RR>>::value ), int> = 0 | |||||
| std::enable_if_t<std::is_pointer_v<RR> | |||||
| && (std::is_class_v<std::remove_pointer_t<RR>> | |||||
| || std::is_union_v<std::remove_pointer_t<RR>>), int> = 0 | |||||
| > | > | ||||
| RR operator->() const noexcept | RR operator->() const noexcept | ||||
| { | { | ||||
| } | } | ||||
| template<class RR = R, | template<class RR = R, | ||||
| std::enable_if_t<( std::is_pointer<RR>::value | |||||
| && !std::is_void<std::remove_pointer_t<RR>>::value), int> = 0> | |||||
| std::enable_if_t<( std::is_pointer_v<RR> | |||||
| && !std::is_void_v<std::remove_pointer_t<RR>>), int> = 0> | |||||
| std::add_lvalue_reference_t<std::remove_pointer_t<RR>> operator*() const noexcept | std::add_lvalue_reference_t<std::remove_pointer_t<RR>> operator*() const noexcept | ||||
| { | { | ||||
| return *get(); | return *get(); | ||||
| template<class RR = R, class DD = D, | template<class RR = R, class DD = D, | ||||
| std::enable_if_t<(std::is_nothrow_move_assignable<RR>::value | |||||
| || std::is_nothrow_copy_assignable<RR>::value) | |||||
| && (std::is_nothrow_move_assignable<DD>::value | |||||
| || std::is_nothrow_copy_assignable<DD>::value), int> = 0 | |||||
| std::enable_if_t<(std::is_nothrow_move_assignable_v<RR> | |||||
| || std::is_nothrow_copy_assignable_v<RR>) | |||||
| && (std::is_nothrow_move_assignable_v<DD> | |||||
| || std::is_nothrow_copy_assignable_v<DD>), int> = 0 | |||||
| > | > | ||||
| unique_resource& operator=(unique_resource&& other) | unique_resource& operator=(unique_resource&& other) | ||||
| { | { | ||||
| { | { | ||||
| reset(); | reset(); | ||||
| if( std::is_nothrow_move_assignable<R>::value == true ) | |||||
| if( std::is_nothrow_move_assignable_v<R> == true ) | |||||
| { | { | ||||
| m_deleter.reset(detail::forward_if_nothrow_move_constructible(other.m_deleter.get())); | m_deleter.reset(detail::forward_if_nothrow_move_constructible(other.m_deleter.get())); | ||||
| m_resource.reset(std::forward<RR>(other.m_resource.get())); | m_resource.reset(std::forward<RR>(other.m_resource.get())); | ||||
| } | } | ||||
| else if( std::is_nothrow_move_assignable<D>::value == true ) | |||||
| else if( std::is_nothrow_move_assignable_v<D> == true ) | |||||
| { | { | ||||
| m_resource.reset(detail::forward_if_nothrow_move_constructible(other.m_resource.get())); | m_resource.reset(detail::forward_if_nothrow_move_constructible(other.m_resource.get())); | ||||
| m_deleter.reset(std::forward<DD>(other.m_deleter.get())); | m_deleter.reset(std::forward<DD>(other.m_deleter.get())); | ||||
| template<class R, class D> | template<class R, class D> | ||||
| unique_resource<std::decay_t<R>, std::decay_t<D>> make_unique_resource(R&& r, D&& d) | unique_resource<std::decay_t<R>, std::decay_t<D>> make_unique_resource(R&& r, D&& d) | ||||
| noexcept(std::is_nothrow_constructible<std::decay_t<R>, R>::value | |||||
| && std::is_nothrow_constructible<std::decay_t<D>, D>::value) | |||||
| noexcept(std::is_nothrow_constructible_v<std::decay_t<R>, R> | |||||
| && std::is_nothrow_constructible_v<std::decay_t<D>, D>) | |||||
| { | { | ||||
| return unique_resource<std::decay_t<R>, std::decay_t<D>>{std::forward<R>(r), std::forward<D>(d)}; | return unique_resource<std::decay_t<R>, std::decay_t<D>>{std::forward<R>(r), std::forward<D>(d)}; | ||||
| } | } | ||||
| template<class R, class D> | template<class R, class D> | ||||
| unique_resource<R&, std::decay_t<D>> make_unique_resource(std::reference_wrapper<R> r, D d) | unique_resource<R&, std::decay_t<D>> make_unique_resource(std::reference_wrapper<R> r, D d) | ||||
| noexcept(std::is_nothrow_constructible<std::decay_t<D>, D>::value) | |||||
| noexcept(std::is_nothrow_constructible_v<std::decay_t<D>, D>) | |||||
| { | { | ||||
| return unique_resource<R&, std::decay_t<D>>(r.get(), std::forward<D>(d)); | return unique_resource<R&, std::decay_t<D>>(r.get(), std::forward<D>(d)); | ||||
| } | } | ||||
| template<class R, class D, class S = R> | template<class R, class D, class S = R> | ||||
| unique_resource<std::decay_t<R>, std::decay_t<D>> make_unique_resource_checked(R&& r, const S& invalid, D&& d) | unique_resource<std::decay_t<R>, std::decay_t<D>> make_unique_resource_checked(R&& r, const S& invalid, D&& d) | ||||
| noexcept(std::is_nothrow_constructible<std::decay_t<R>, R>::value | |||||
| && std::is_nothrow_constructible<std::decay_t<D>, D>::value) | |||||
| noexcept(std::is_nothrow_constructible_v<std::decay_t<R>, R> | |||||
| && std::is_nothrow_constructible_v<std::decay_t<D>, D>) | |||||
| { | { | ||||
| const bool must_release{r == invalid}; | const bool must_release{r == invalid}; | ||||
| auto ur = make_unique_resource(r, d); | auto ur = make_unique_resource(r, d); |