| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502 | #ifndef __GBLIBCPP_LIST__#define __GBLIBCPP_LIST__#include <bits/compressed_pair>#include <bits/iter_ops>#include <memory>#include <initializer_list>#include <type_traits>#include <utility>#include <cstddef>namespace std {template <typename T, typename Allocator = std::allocator<T>>class list {private:    struct node_base {        node_base* prev;        node_base* next;        constexpr node_base() noexcept            : prev { this }, next { this } {}        constexpr void connect(node_base* _next) noexcept        {            this->next = _next;            _next->prev = static_cast<node_base*>(this);        }        constexpr void swap(node_base& other) noexcept        {            std::swap(prev, other.prev);            std::swap(next, other.next);        }    };    struct node : public node_base {        T value;        template <typename... Args>        explicit constexpr node(Args&&... args)            : value(std::forward<Args>(args)...) { }    };public:    template <bool Const>    class _iterator;public:    using value_type = T;    using allocator_type = Allocator;    using size_type = std::size_t;    using difference_type = std::ptrdiff_t;    using reference = T&;    using const_reference = const T&;    using pointer = typename std::allocator_traits<Allocator>::pointer;    using const_pointer = typename        std::allocator_traits<Allocator>::const_pointer;    using iterator = _iterator<false>;    using const_iterator = _iterator<true>;private:    using alloc_traits = std::allocator_traits<allocator_type>;    using node_alloc_type = typename        std::allocator_traits<Allocator>::template rebind_alloc<node>;    using node_alloc_traits = std::allocator_traits<node_alloc_type>;public:    template <bool Const>    class _iterator {    public:        using const_node_pointer = const node_base*;        using node_pointer = node_base*;        using value_type = std::conditional_t<Const, const T, T>;        using pointer = std::add_pointer_t<value_type>;        using reference = std::add_lvalue_reference_t<value_type>;        friend class list;    private:        node_pointer p;    public:        constexpr _iterator() noexcept = default;        explicit constexpr _iterator(const_node_pointer p)            : p { const_cast<node_pointer>(p) } {}        constexpr _iterator(const _iterator& iter) noexcept = default;        constexpr _iterator(_iterator&& iter) noexcept = default;        constexpr ~_iterator() = default;        constexpr _iterator& operator=(const _iterator& iter) noexcept = default;        constexpr _iterator& operator=(_iterator&& iter) noexcept = default;        constexpr bool operator==(const _iterator& iter) const noexcept = default;        constexpr reference operator*() const noexcept        { return ((node*)p)->value; }        constexpr pointer operator&() const noexcept        { return std::addressof(this->operator*()); }        constexpr pointer operator->() const noexcept        { return this->operator&(); }        constexpr _iterator& operator++() noexcept        { p = p->next; return *this; }        constexpr _iterator operator++(int) noexcept        { _iterator ret(p); (void)this->operator++(); return ret; }        constexpr _iterator& operator--(void) noexcept        { p = p->prev; return *this; }        constexpr _iterator operator--(int) noexcept        { _iterator ret(p); (void)this->operator--(); return ret; }        constexpr operator bool() const { return p; }        constexpr operator _iterator<true>() const { return _iterator<true> { p }; }    };private:    node_base m_head;    impl::compressed_pair<size_type, node_alloc_type> m_pair;private:    // move m_head and m_size of other to *this    // other MUST NOT be empty, *this MUST be empty    constexpr void _move_from(list&& other) noexcept    {        std::swap(_size(), other._size());        other.m_head.prev->connect(&m_head);        m_head.connect(other.m_head.next);        other.m_head.next = other.m_head.prev = &other.m_head;    }    constexpr size_type& _size() noexcept { return m_pair.first(); }    constexpr const size_type& _size() const noexcept { return m_pair.first(); }    constexpr node_alloc_type& _alloc() noexcept { return m_pair.second(); }    constexpr const node_alloc_type& _alloc() const noexcept { return m_pair.second(); }public:    __GBLIBCPP_CONSTEXPR    iterator end(void) noexcept { return iterator { &m_head }; }    __GBLIBCPP_CONSTEXPR    const_iterator cend(void) const noexcept { return const_iterator { &m_head }; }    __GBLIBCPP_CONSTEXPR    const_iterator end(void) const noexcept { return cend(); }    __GBLIBCPP_CONSTEXPR    iterator begin(void) noexcept { return iterator { m_head.next }; }    __GBLIBCPP_CONSTEXPR    const_iterator cbegin(void) const noexcept    { return const_iterator { m_head.next }; }    __GBLIBCPP_CONSTEXPR    const_iterator begin(void) const noexcept { return cbegin(); }    template <typename... Args>    __GBLIBCPP_CONSTEXPR    iterator emplace(const_iterator pos, Args&&... args)    {        node* nd = node_alloc_traits::allocate(_alloc(), 1);        node_alloc_traits::construct(_alloc(), nd, std::forward<Args>(args)...);        nd->next = pos.p;        nd->prev = pos.p->prev;        nd->next->prev = nd;        nd->prev->next = nd;        ++_size();        return iterator { nd };    }    explicit __GBLIBCPP_CONSTEXPR    list(const Allocator& alloc): m_head{}, m_pair{0, alloc} { }    __GBLIBCPP_CONSTEXPR    list(): list(Allocator()) {}    __GBLIBCPP_CONSTEXPR    explicit list(size_type count, const Allocator& alloc = Allocator()): list(alloc)    {        while (count--)            emplace_back();    }    __GBLIBCPP_CONSTEXPR    list(size_type count, const T& value, const Allocator& alloc = Allocator()): list(alloc)    {        while (count--)            emplace_back(value);    }    template <typename InputIter>    __GBLIBCPP_CONSTEXPR    list(InputIter first, InputIter last, const Allocator& alloc = Allocator())        : list(alloc) { insert(first, last); }    __GBLIBCPP_CONSTEXPR    list(const list& other, const Allocator& alloc): list(alloc)    {        // TODO: select_on_container_copy_construction        for (const auto& item : other)            emplace_back(item);    }    __GBLIBCPP_CONSTEXPR    list(const list& other): list(other,            alloc_traits::select_on_container_copy_construction(_alloc())) { }    __GBLIBCPP_CONSTEXPR    list(list&& other): m_head{}, m_pair{0, std::move(other._alloc())}    {        if (other.empty())            return;        _move_from(std::move(other));    }    __GBLIBCPP_CONSTEXPR    list(list&& other, const Allocator& alloc): m_head{}, m_pair{0, alloc}    {        if (other._alloc() != alloc) {            for (auto iter = other.begin(); iter != other.end(); ++iter)                emplace(cend(), std::move(*iter));            other.clear();            return;        }        // other._alloc() == alloc        if (other.empty())            return;        _move_from(std::move(other));    }    __GBLIBCPP_CONSTEXPR    list(std::initializer_list<T> ilist,        const Allocator& alloc = Allocator())        : list(alloc)    {        for (const auto& item : ilist)            emplace_back(item);    }    __GBLIBCPP_CONSTEXPR    ~list()    {        clear();        m_head.next = m_head.prev = nullptr;    }    __GBLIBCPP_CONSTEXPR    list& operator=(const list& other)    {        // TODO: reuse memory if _alloc() == other._alloc()        clear();        if constexpr (alloc_traits::            propagate_on_container_copy_assignment::value)            _alloc() = other._alloc();        for (const auto& item : other)            emplace_back(item);        return *this;    }    __GBLIBCPP_CONSTEXPR    list& operator=(list&& other)    {        if (alloc_traits::            propagate_on_container_move_assignment::value) {            clear();            _alloc() = std::move(other._alloc());            if (other.empty())                return *this;            _move_from(std::move(other));            return *this;        }        // TODO: reuse memory if _alloc() == other._alloc()        clear();        if (_alloc() != other._alloc()) {            for (auto iter = other.begin(); iter != other.end(); ++iter)                emplace(cend(), std::move(*iter));            other.clear();            return *this;        }        _move_from(std::move(other));        return *this;    }    __GBLIBCPP_CONSTEXPR    list& operator=(std::initializer_list<T> ilist)    {        // TODO: reuse memory        clear();        for (const auto& item : ilist)            emplace_back(item);        return *this;    }    __GBLIBCPP_CONSTEXPR    void assign(size_type count, const T& value)    {        clear();        while (count--)            emplace_back(value);    }    template <typename InputIter>    __GBLIBCPP_CONSTEXPR    void assign(InputIter first, InputIter last)    {        clear();        insert(first, last);    }    __GBLIBCPP_CONSTEXPR    void assign(std::initializer_list<T> ilist)    {        clear();        for (const auto& item : ilist)            emplace_back(item);    }    __GBLIBCPP_CONSTEXPR    allocator_type get_allocator() const noexcept { return _alloc(); }    __GBLIBCPP_CONSTEXPR    reference front() { return *begin(); }    __GBLIBCPP_CONSTEXPR    const_reference front() const { return *cbegin(); }    __GBLIBCPP_CONSTEXPR    reference back() { return *--end(); }    __GBLIBCPP_CONSTEXPR    const_reference back() const { return *--cend(); }    __GBLIBCPP_CONSTEXPR    iterator insert(const_iterator pos, const T& value)    { return emplace(pos, value); }    __GBLIBCPP_CONSTEXPR    iterator insert(const_iterator pos, T&& value)    { return emplace(pos, std::move(value)); }    __GBLIBCPP_CONSTEXPR    iterator insert(const_iterator pos, size_type count, const T& value)    {        if (!(count--))            return pos;        auto ret = insert(pos, value);        while (count--)            insert(pos, value);        return ret;    }    template <typename InputIter>    __GBLIBCPP_CONSTEXPR    void insert(InputIter first, InputIter last)    {        for ( ; first != last; ++first)            emplace_back(*first);    }    template <typename... Args>    __GBLIBCPP_CONSTEXPR    reference emplace_back(Args&&... args)    { return *emplace(end(), std::forward<Args>(args)...); }    template <typename... Args>    __GBLIBCPP_CONSTEXPR    reference emplace_front(Args&&... args)    { return *emplace(begin(), std::forward<Args>(args)...); }    __GBLIBCPP_CONSTEXPR    void push_back(const T& value)    { emplace_back(value); }    __GBLIBCPP_CONSTEXPR    void push_back(T&& value)    { emplace_back(std::move(value)); }    __GBLIBCPP_CONSTEXPR    void push_front(const T& value)    { emplace_front(value); }    __GBLIBCPP_CONSTEXPR    void push_front(T&& value)    { emplace_front(std::move(value)); }    __GBLIBCPP_CONSTEXPR    void pop_back() { erase(--end()); }    __GBLIBCPP_CONSTEXPR    void pop_front() { erase(begin()); }    __GBLIBCPP_CONSTEXPR    iterator erase(const_iterator pos) noexcept    {        iterator ret { pos.p->next };        pos.p->next->prev = pos.p->prev;        pos.p->prev->next = pos.p->next;        node_alloc_traits::destroy(_alloc(), (node*)pos.p);        node_alloc_traits::deallocate(_alloc(), (node*)pos.p, 1);        --_size();        return ret;    }    __GBLIBCPP_CONSTEXPR    iterator erase(const_iterator first, const_iterator last) noexcept    {        while (first != last)            first = erase(first);        return first;    }    __GBLIBCPP_CONSTEXPR    void clear() noexcept    {        for (auto iter = begin(); iter != end(); )            iter = erase(iter);    }    __GBLIBCPP_CONSTEXPR    size_type size() const noexcept { return _size(); }    __GBLIBCPP_CONSTEXPR    bool empty() const noexcept { return size() == 0; }    __GBLIBCPP_CONSTEXPR    void swap(list& other)    {        if constexpr (alloc_traits::propagate_on_container_swap::value)            std::swap(_alloc(), other._alloc());        std::swap(_size(), other.m_size);        std::swap(m_head, other.m_head);        std::swap(m_head.next->prev, other.m_head.next->prev);        std::swap(m_head.prev->next, other.m_head.prev->next);    }    __GBLIBCPP_CONSTEXPR    void resize(size_type count)    {        while (count > size())            emplace_back();        while (count < size())            pop_back();    }    __GBLIBCPP_CONSTEXPR    void resize(size_type count, const value_type& value)    {        while (count > size())            emplace_back(value);        while (count < size())            pop_back();    }    __GBLIBCPP_CONSTEXPR    size_type remove(const T& value)    {        size_type retval = 0;        for (auto iter = begin(); iter != end(); ) {            if (value != *iter) {                ++iter;                continue;            }            ++retval;            iter = erase(iter);        }        return retval;    }    template <typename UnaryPredicate>    __GBLIBCPP_CONSTEXPR    size_type remove_if(UnaryPredicate p)    {        size_type retval = 0;        for (auto iter = begin(); iter != end(); ) {            if (!p(*iter)) {                ++iter;                continue;            }            ++retval;            iter = erase(iter);        }        return retval;    }};template <typename T, typename Allocator>void swap(std::list<T, Allocator>& lhs,    std::list<T, Allocator>& rhs) { lhs.swap(rhs); }template <typename T, typename Allocator, typename U>typename std::list<T, Allocator>::size_type    erase(std::list<T, Allocator>& l, const U& value){    return l.remove_if([&](auto& elem) { return elem == value; });}template <typename T, typename Allocator, typename Predicate>typename std::list<T, Allocator>::size_type    erase_if(std::list<T, Allocator>& l, Predicate p){ return l.remove_if(p); }} // namespace std#endif
 |