Changeset 40340461 in mainline


Ignore:
Timestamp:
2018-07-05T21:41:20Z (6 years ago)
Author:
Dzejrou <dzejrou@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
4bea22a
Parents:
7e7c1aac
git-author:
Dzejrou <dzejrou@…> (2018-03-28 14:22:48)
git-committer:
Dzejrou <dzejrou@…> (2018-07-05 21:41:20)
Message:

cpp: added unique_ptr

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/cpp/include/impl/memory.hpp

    r7e7c1aac r40340461  
    428428        return first;
    429429    }
     430
     431    /**
     432     * 20.8, smart pointers:
     433     */
     434
     435    template<class T>
     436    struct default_delete
     437    {
     438        default_delete() noexcept = default;
     439
     440        template<class U, class = enable_if_t<is_convertible_v<U*, T*>, void>>
     441        default_delete(const default_delete<U>&) noexcept
     442        { /* DUMMY BODY */ }
     443
     444        template<class U>
     445        void operator()(U* ptr)
     446        {
     447            delete ptr;
     448        }
     449    };
     450
     451    template<class T>
     452    struct default_delete<T[]>
     453    {
     454        default_delete() noexcept = default;
     455
     456        template<class U, class = enable_if_t<is_convertible_v<U(*)[], T(*)[]>, void>>
     457        default_delete(const default_delete<U[]>&) noexcept
     458        { /* DUMMY BODY */ }
     459
     460        template<class U, class = enable_if_t<is_convertible_v<U(*)[], T(*)[]>, void>>
     461        void operator()(U* ptr)
     462        {
     463            delete[] ptr;
     464        }
     465    };
     466
     467    template<class T, class D = default_delete<T>>
     468    class unique_ptr;
     469
     470    namespace aux
     471    {
     472        template<class P, class D, class = void>
     473        struct get_unique_pointer: type_is<typename P::element_type*>
     474        { /* DUMMY BODY */ };
     475
     476        template<class P, class D>
     477        struct get_unique_pointer<P, D, void_t<typename remove_reference_t<D>::pointer>>
     478            : type_is<typename remove_reference_t<D>::pointer>
     479        { /* DUMMY BODY */ };
     480    }
     481
     482    template<class T, class D>
     483    class unique_ptr
     484    {
     485        public:
     486            using element_type = T;
     487            using deleter_type = D;
     488            using pointer      = typename aux::get_unique_pointer<unique_ptr<T, D>, D>::type;
     489
     490            /**
     491             * 20.8.1.2.1, constructors:
     492             */
     493
     494            constexpr unique_ptr() noexcept
     495                : ptr_{}, deleter_{}
     496            { /* DUMMY BODY */ }
     497
     498            explicit unique_ptr(pointer ptr) noexcept
     499                : ptr_{ptr}, deleter_{}
     500            { /* DUMMY BODY */ }
     501
     502            unique_ptr(pointer ptr, /* TODO */ int d) noexcept;
     503
     504            unique_ptr(pointer ptr, /* TODO */ char d) noexcept;
     505
     506            unique_ptr(unique_ptr&& other)
     507                : ptr_{move(other.ptr_)}, deleter_{forward<deleter_type>(other.deleter_)}
     508            {
     509                other.ptr_ = nullptr;
     510            }
     511
     512            constexpr unique_ptr(nullptr_t)
     513                : unique_ptr{}
     514            { /* DUMMY BODY */ }
     515
     516            template<
     517                class U, class E,
     518                class = enable_if_t<
     519                    is_convertible_v<
     520                        typename unique_ptr<U, E>::pointer,
     521                        pointer
     522                    >, void
     523                >
     524            >
     525            unique_ptr(unique_ptr<U, E>&& other) noexcept
     526                : ptr_{move(other.ptr_)}, deleter_{forward<D>(other.deleter_)}
     527            {
     528                other.ptr_ = nullptr;
     529            }
     530
     531            /**
     532             * 20.8.1.2.2, destructor:
     533             */
     534
     535            ~unique_ptr()
     536            {
     537                if (ptr_)
     538                    deleter_(ptr_);
     539            }
     540
     541            /**
     542             * 20.8.1.2.3, assignment:
     543             */
     544
     545            unique_ptr& operator=(unique_ptr&& rhs) noexcept
     546            {
     547                reset(rhs.release());
     548                deleter_ = forward<deleter_type>(rhs.get_deleter());
     549
     550                return *this;
     551            }
     552
     553            template<
     554                class U, class E,
     555                class = enable_if_t<
     556                    is_convertible_v<
     557                        typename unique_ptr<U, E>::pointer,
     558                        pointer
     559                    > && !is_array_v<U>, void
     560                >
     561            >
     562            unique_ptr& operator=(unique_ptr<U, E>&& rhs) noexcept
     563            {
     564                reset(rhs.release());
     565                deleter_ = forward<E>(rhs.get_deleter());
     566
     567                return *this;
     568            }
     569
     570            unique_ptr& operator=(nullptr_t) noexcept
     571            {
     572                reset();
     573
     574                return *this;
     575            }
     576
     577            /**
     578             * 20.8.1.2.4, observers:
     579             */
     580
     581            add_lvalue_reference_t<element_type> operator*() const
     582            {
     583                return *ptr_;
     584            }
     585
     586            pointer operator->() const noexcept
     587            {
     588                return ptr_;
     589            }
     590
     591            pointer get() const noexcept
     592            {
     593                return ptr_;
     594            }
     595
     596            deleter_type& get_deleter() noexcept
     597            {
     598                return deleter_;
     599            }
     600
     601            const deleter_type& get_deleter() const noexcept
     602            {
     603                return deleter_;
     604            }
     605
     606            explicit operator bool() const noexcept
     607            {
     608                return ptr_ != nullptr;
     609            }
     610
     611            /**
     612             * 20.8.1.2.5, modifiers:
     613             */
     614
     615            pointer release() noexcept
     616            {
     617                auto ret = ptr_;
     618                ptr_ = nullptr;
     619
     620                return ret;
     621            }
     622
     623            void reset(pointer ptr = pointer{}) noexcept
     624            {
     625                /**
     626                 * Note: Order is significant, deleter may delete
     627                 *       *this.
     628                 */
     629                auto old = ptr_;
     630                ptr_ = ptr;
     631
     632                if (old)
     633                    deleter_(old);
     634            }
     635
     636            void swap(unique_ptr& other) noexcept
     637            {
     638                std::swap(ptr_, other.ptr_);
     639                std::swap(deleter_, other.deleter_);
     640            }
     641
     642            unique_ptr(const unique_ptr&) = delete;
     643            unique_ptr& operator=(const unique_ptr&) = delete;
     644
     645        private:
     646            pointer ptr_;
     647            deleter_type deleter_;
     648    };
     649
     650    namespace aux
     651    {
     652        template<class From, class To>
     653        struct is_convertible_array: is_convertible<From(*)[], To(*)[]>
     654        { /* DUMMY BODY */ };
     655
     656        template<class From, class To>
     657        inline constexpr bool is_convertible_array_v = is_convertible_array<From, To>::value;
     658
     659        template<class T, class D, class U, class E>
     660        struct compatible_ptrs: integral_constant<
     661              bool,
     662              is_array_v<U> && is_same_v<
     663                typename unique_ptr<T, D>::pointer,
     664                typename unique_ptr<T, D>::element_type*
     665              > && is_same_v<
     666                typename unique_ptr<U, E>::pointer,
     667                typename unique_ptr<U, E>::element_type*
     668              > && is_convertible_array_v<
     669                typename unique_ptr<T, D>::element_type,
     670                typename unique_ptr<U, E>::element_type
     671              > && ((is_reference_v<D> && is_same_v<D, E>) ||
     672                   (!is_reference_v<D> && is_convertible_v<E, D>))
     673        >
     674        { /* DUMMY BODY */ };
     675
     676        template<class T, class D, class U, class E>
     677        inline constexpr bool compatible_ptrs_v = compatible_ptrs<T, D, U, E>::value;
     678    }
     679
     680    template<class T, class D>
     681    class unique_ptr<T[], D>
     682    {
     683        public:
     684            using element_type = T;
     685            using deleter_type = D;
     686            using pointer      = typename aux::get_unique_pointer<unique_ptr<T[], D>, D>::type;
     687
     688            /**
     689             * 20.8.1.3.1, constructors:
     690             */
     691
     692            constexpr unique_ptr() noexcept
     693                : ptr_{}, deleter_{}
     694            { /* DUMMY BODY */ }
     695
     696            template<
     697                class U,
     698                class = enable_if_t<
     699                    is_same_v<U, T> || aux::is_convertible_array_v<U, T>, void
     700                >
     701            >
     702            explicit unique_ptr(U ptr) noexcept
     703                : ptr_{ptr}, deleter_{}
     704            { /* DUMMY BODY */ }
     705
     706            template<
     707                class U, class E,
     708                class = enable_if_t<aux::compatible_ptrs_v<T, D, U, E>, void>
     709            >
     710            unique_ptr(U ptr, /* TODO */ int d) noexcept;
     711
     712            template<
     713                class U, class E,
     714                class = enable_if_t<aux::compatible_ptrs_v<T, D, U, E>, void>
     715            >
     716            unique_ptr(U ptr, /* TODO */ char d) noexcept;
     717
     718            unique_ptr(unique_ptr&& other) noexcept
     719                : ptr_{move(other.ptr_)}, deleter_{forward<deleter_type>(other.deleter_)}
     720            {
     721                other.ptr_ = nullptr;
     722            }
     723
     724            template<
     725                class U, class E,
     726                class = enable_if_t<
     727                    is_same_v<U, pointer> ||
     728                    (is_same_v<pointer, element_type*> && is_pointer_v<U> &&
     729                     aux::is_convertible_array_v<remove_pointer_t<U>, element_type>),
     730                    void
     731                >
     732            >
     733            unique_ptr(unique_ptr<U, E>&& other) noexcept
     734                : ptr_{move(other.ptr_)}, deleter_{forward<D>(other.deleter_)}
     735            {
     736                other.ptr_ = nullptr;
     737            }
     738
     739            constexpr unique_ptr(nullptr_t) noexcept
     740                : unique_ptr{}
     741            { /* DUMMY BODY */ }
     742
     743            ~unique_ptr()
     744            {
     745                if (ptr_)
     746                    deleter_(ptr_);
     747            }
     748
     749            /**
     750             * 20.8.1.3.2, assignment:
     751             */
     752
     753            unique_ptr& operator=(unique_ptr&& rhs) noexcept
     754            {
     755                reset(rhs.release());
     756                deleter_ = forward<deleter_type>(rhs.get_deleter());
     757
     758                return *this;
     759            }
     760
     761            template<
     762                class U, class E,
     763                class = enable_if_t<aux::compatible_ptrs_v<T, D, U, E>, void>
     764            >
     765            unique_ptr& operator=(unique_ptr<U, E>&& rhs) noexcept
     766            {
     767                reset(rhs.release());
     768                deleter_ = forward<E>(rhs.get_deleter());
     769
     770                return *this;
     771            }
     772
     773            unique_ptr& operator=(nullptr_t) noexcept
     774            {
     775                reset();
     776
     777                return *this;
     778            }
     779
     780            /**
     781             * 20.8.1.3.3, observers:
     782             */
     783
     784            element_type& operator[](size_t idx) const
     785            {
     786                return ptr_[idx];
     787            }
     788
     789            pointer get() const noexcept
     790            {
     791                return ptr_;
     792            }
     793
     794            deleter_type& get_deleter() noexcept
     795            {
     796                return deleter_;
     797            }
     798
     799            const deleter_type& get_deleter() const noexcept
     800            {
     801                return deleter_;
     802            }
     803
     804            explicit operator bool() const noexcept
     805            {
     806                return ptr_ != nullptr;
     807            }
     808
     809            /**
     810             * 20.8.1.3.4, modifiers:
     811             */
     812
     813            pointer release() noexcept
     814            {
     815                auto ret = ptr_;
     816                ptr_ = nullptr;
     817
     818                return ret;
     819            }
     820
     821            template<
     822                class U,
     823                class = enable_if_t<
     824                    is_same_v<U, pointer> ||
     825                    (is_same_v<pointer, element_type*> && is_pointer_v<U> &&
     826                     aux::is_convertible_array_v<remove_pointer_t<U>, element_type>),
     827                    void
     828                >
     829            >
     830            void reset(U ptr) noexcept
     831            {
     832                /**
     833                 * Note: Order is significant, deleter may delete
     834                 *       *this.
     835                 */
     836                auto old = ptr_;
     837                ptr_ = ptr;
     838
     839                if (old)
     840                    deleter_(old);
     841            }
     842
     843            void reset(nullptr_t = nullptr) noexcept
     844            {
     845                reset(pointer{});
     846            }
     847
     848            void swap(unique_ptr& other) noexcept
     849            {
     850                std::swap(ptr_, other.ptr_);
     851                std::swap(deleter_, other.deleter_);
     852            }
     853
     854            unique_ptr(const unique_ptr&) = delete;
     855            unique_ptr& operator=(const unique_ptr&) = delete;
     856
     857        private:
     858            pointer ptr_;
     859            deleter_type deleter_;
     860    };
     861
     862    namespace aux
     863    {
     864        template<class T>
     865        struct is_unbound_array: false_type
     866        { /* DUMMY BODY */ };
     867
     868        template<class T>
     869        struct is_unbound_array<T[]>: true_type
     870        { /* DUMMY BODY */ };
     871
     872        template<class T>
     873        struct is_bound_array: false_type
     874        { /* DUMMY BODY */ };
     875
     876        template<class T, size_t N>
     877        struct is_bound_array<T[N]>: true_type
     878        { /* DUMMY BODY */ };
     879    }
     880
     881    template<
     882        class T, class... Args,
     883        class = enable_if_t<!is_array_v<T>, void>
     884    >
     885    unique_ptr<T> make_unique(Args&&... args)
     886    {
     887        return unique_ptr<T>(new T(forward<Args>(args)...));
     888    }
     889
     890    template<
     891        class T, class = enable_if_t<aux::is_unbound_array<T>::value, void>
     892    >
     893    unique_ptr<T> make_unique(size_t n)
     894    {
     895        return unique_ptr<T>(new remove_extent_t<T>[n]());
     896    }
     897
     898    template<
     899        class T, class... Args,
     900        class = enable_if_t<aux::is_bound_array<T>::value, void>
     901    >
     902    void make_unique(Args&&...) = delete;
     903
     904    template<class T, class D>
     905    void swap(unique_ptr<T, D>& lhs, unique_ptr<T, D>& rhs) noexcept
     906    {
     907        lhs.swap(rhs);
     908    }
     909
     910    template<class T1, class D1, class T2, class D2>
     911    bool operator==(const unique_ptr<T1, D1>& lhs,
     912                    const unique_ptr<T2, D2>& rhs)
     913    {
     914        return lhs.get() == rhs.get();
     915    }
     916
     917    template<class T1, class D1, class T2, class D2>
     918    bool operator!=(const unique_ptr<T1, D1>& lhs,
     919                    const unique_ptr<T2, D2>& rhs)
     920    {
     921        return lhs.get() != rhs.get();
     922    }
     923
     924    template<class T1, class D1, class T2, class D2>
     925    bool operator<(const unique_ptr<T1, D1>& lhs,
     926                   const unique_ptr<T2, D2>& rhs)
     927    {
     928        return lhs.get() < rhs.get();
     929    }
     930
     931    template<class T1, class D1, class T2, class D2>
     932    bool operator<=(const unique_ptr<T1, D1>& lhs,
     933                    const unique_ptr<T2, D2>& rhs)
     934    {
     935        return !(rhs < lhs);
     936    }
     937
     938    template<class T1, class D1, class T2, class D2>
     939    bool operator>(const unique_ptr<T1, D1>& lhs,
     940                   const unique_ptr<T2, D2>& rhs)
     941    {
     942        return rhs < lhs;
     943    }
     944
     945    template<class T1, class D1, class T2, class D2>
     946    bool operator>=(const unique_ptr<T1, D1>& lhs,
     947                    const unique_ptr<T2, D2>& rhs)
     948    {
     949        return !(lhs < rhs);
     950    }
     951
     952    template<class T, class D>
     953    bool operator==(const unique_ptr<T, D>& ptr, nullptr_t) noexcept
     954    {
     955        return !ptr;
     956    }
     957
     958    template<class T, class D>
     959    bool operator==(nullptr_t, const unique_ptr<T, D>& ptr) noexcept
     960    {
     961        return !ptr;
     962    }
     963
     964    template<class T, class D>
     965    bool operator!=(const unique_ptr<T, D>& ptr, nullptr_t) noexcept
     966    {
     967        return static_cast<bool>(ptr);
     968    }
     969
     970    template<class T, class D>
     971    bool operator!=(nullptr_t, const unique_ptr<T, D>& ptr) noexcept
     972    {
     973        return static_cast<bool>(ptr);
     974    }
     975
     976    template<class T, class D>
     977    bool operator<(const unique_ptr<T, D>& ptr, nullptr_t)
     978    {
     979        return ptr.get() < nullptr;
     980    }
     981
     982    template<class T, class D>
     983    bool operator<(nullptr_t, const unique_ptr<T, D>& ptr)
     984    {
     985        return nullptr < ptr.get();
     986    }
     987
     988    template<class T, class D>
     989    bool operator<=(const unique_ptr<T, D>& ptr, nullptr_t)
     990    {
     991        return !(nullptr < ptr);
     992    }
     993
     994    template<class T, class D>
     995    bool operator<=(nullptr_t, const unique_ptr<T, D>& ptr)
     996    {
     997        return !(ptr < nullptr);
     998    }
     999
     1000    template<class T, class D>
     1001    bool operator>(const unique_ptr<T, D>& ptr, nullptr_t)
     1002    {
     1003        return nullptr < ptr;
     1004    }
     1005
     1006    template<class T, class D>
     1007    bool operator>(nullptr_t, const unique_ptr<T, D>& ptr)
     1008    {
     1009        return ptr < nullptr;
     1010    }
     1011
     1012    template<class T, class D>
     1013    bool operator>=(const unique_ptr<T, D>& ptr, nullptr_t)
     1014    {
     1015        return !(ptr < nullptr);
     1016    }
     1017
     1018    template<class T, class D>
     1019    bool operator>=(nullptr_t, const unique_ptr<T, D>& ptr)
     1020    {
     1021        return !(nullptr < ptr);
     1022    }
    4301023}
    4311024
Note: See TracChangeset for help on using the changeset viewer.