| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501 | #ifndef __GBLIBCPP_VECTOR__#define __GBLIBCPP_VECTOR__#include <bits/iter_ops>#include <functional>#include <memory>#include <initializer_list>#include <cstddef>namespace std {template <typename T, typename Allocator = std::allocator<T>>class vector {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&;    template <bool Const>    class _iterator {    public:        // TODO:        // using iterator_category = std::random_access_iterator_tag;        using value_type = std::conditional_t<Const, const T, T>;        using difference_type = std::ptrdiff_t;        using pointer = std::add_pointer_t<value_type>;        using reference = std::add_lvalue_reference_t<value_type>;    private:        T* m_ptr;    public:        constexpr _iterator(void) noexcept : m_ptr() {}        constexpr explicit _iterator(const T* ptr) noexcept            : m_ptr(const_cast<T*>(ptr)) {}        constexpr _iterator(const _iterator& other) noexcept = default;        constexpr _iterator(_iterator&& other) noexcept = default;        constexpr _iterator& operator=(const _iterator& other) noexcept = default;        constexpr _iterator& operator=(_iterator&& other) noexcept = default;        constexpr bool operator==(const _iterator& other) const noexcept = default;        constexpr reference operator*() const noexcept { return *m_ptr; }        constexpr pointer operator&() const noexcept        { return std::addressof(this->operator*()); }        constexpr pointer operator->() const noexcept        { return this->operator&(); }        constexpr _iterator& operator++() noexcept        { ++m_ptr; return *this; }        constexpr _iterator operator++(int) noexcept        { _iterator ret(m_ptr); (void)this->operator++(); return ret; }        constexpr _iterator& operator--(void) noexcept        { --m_ptr; return *this; }        constexpr _iterator operator--(int) noexcept        { _iterator ret(m_ptr); (void)this->operator--(); return ret; }        constexpr _iterator& operator+=(difference_type n) noexcept        { m_ptr += n; return *this; }        constexpr _iterator& operator-=(difference_type n) noexcept        { m_ptr -= n; return *this; }        constexpr _iterator operator+(difference_type n) const noexcept        { return _iterator { m_ptr + n }; }        constexpr _iterator operator-(difference_type n) const noexcept        { return _iterator { m_ptr - n }; }        constexpr difference_type operator-(const _iterator& other) const noexcept        { return m_ptr - other.m_ptr; }        constexpr reference operator[](difference_type n) const noexcept        { return m_ptr[n]; }        constexpr operator bool() { return m_ptr; }        constexpr operator _iterator<true>() { return _iterator<true> { m_ptr }; }        constexpr operator _iterator<false>() { return _iterator<false> { m_ptr }; }        constexpr operator const T*() { return m_ptr; }    };private:    using alloc_traits = std::allocator_traits<Allocator>;public:    using pointer = typename alloc_traits::pointer;    using const_pointer = typename alloc_traits::const_pointer;    using iterator = _iterator<false>;    using const_iterator = _iterator<true>;private:    T* m_data;    size_type m_size;    size_type m_capacity;    allocator_type m_alloc;private:    // assert(n >= m_size)    constexpr void _reallocate_safe(size_type n)    {        T* newptr = nullptr;        if (n)            newptr = alloc_traits::allocate(m_alloc, n);        for (size_t i = 0; i < m_size; ++i) {            if (n)                alloc_traits::construct(m_alloc, newptr + i, std::move(m_data[i]));            alloc_traits::destroy(m_alloc, m_data + i);        }        alloc_traits::deallocate(m_alloc, m_data, m_capacity);        m_data = newptr;        m_capacity = n;    }    // make m_capacity >= n >= m_size    constexpr void _pre_resize(size_type n)    {        if (n < m_size) {            while (n < m_size)                pop_back();        }        else if (n > m_size) {            reserve(n);        }    }public:    constexpr vector(void)        noexcept(noexcept(Allocator()))        : m_data(), m_size(), m_capacity(), m_alloc() {}    constexpr explicit vector(const Allocator& alloc) noexcept        : m_data(), m_size(), m_capacity(), m_alloc(alloc) {}    constexpr vector(size_type n, const T& val,        const Allocator& alloc = Allocator())        : vector(alloc) { resize(n, val); }    constexpr explicit vector(size_type n,        const Allocator& alloc = Allocator())        : vector(alloc) { resize(n); }    // TODO: check whether InputIter satisfies LegacyInputIterator    template <typename InputIter>    constexpr vector(InputIter first, InputIter last,        const Allocator& alloc = Allocator())        : vector(alloc) { insert(cbegin(), first, last); }    constexpr vector(const vector& other)        : vector(std::allocator_traits<allocator_type>::            select_on_container_copy_construction(other.m_alloc))    { insert(cbegin(), other.begin(), other.end()); }    constexpr vector(const vector& other, const Allocator& alloc)        : vector(alloc) { insert(cbegin(), other.begin(), other.end()); }    constexpr vector(vector&& other) noexcept        : m_data(std::exchange(other.m_data, nullptr))        , m_size(std::exchange(other.m_size, 0))        , m_capacity(std::exchange(other.m_capacity, 0))        , m_alloc(std::move(other.m_alloc)) {}        constexpr vector(vector&& other, const Allocator& alloc)        : vector(alloc)    {        if (alloc == other.get_allocator()) {            m_data = std::exchange(other.m_data, nullptr);            m_size = std::exchange(other.m_size, 0);            m_capacity = std::exchange(other.m_capacity, 0);        } else {            // TODO: std::move_iterator            // insert(cbegin(), std::make_move_iterator(other.begin()),            //     std::make_move_iterator(other.end()));            for (auto& item : other)                emplace_back(std::move(item));        }    }    constexpr vector(std::initializer_list<T> init,        const Allocator& alloc = Allocator())        : vector(alloc) { insert(cbegin(), init.begin(), init.end()); }    constexpr ~vector()    {        resize(0);        shrink_to_fit();    }    constexpr vector& operator=(const vector& other)    {        clear();        if constexpr (alloc_traits::            propagate_on_container_copy_assignment::value) {            if (m_alloc != other.m_alloc)                shrink_to_fit();            m_alloc = other.m_alloc;        }        insert(cbegin(), other.begin(), other.end());        return *this;    }    constexpr vector& operator=(vector&& other)    {        clear();        if constexpr (alloc_traits::            propagate_on_container_move_assignment::value) {            shrink_to_fit();            m_alloc = std::move(other.m_alloc);        }        else {            if (m_alloc != other.m_alloc) {                // TODO: std::move_iterator                for (auto& item : other)                    emplace_back(std::move(item));                return *this;            }            shrink_to_fit();        }        m_data = std::exchange(other.m_data, nullptr);        m_size = std::exchange(other.m_size, 0);        m_capacity = std::exchange(other.m_capacity, 0);        return *this;    }    constexpr vector& operator=(std::initializer_list<T> init)    {        assign(init.begin(), init.end());        return *this;    }    constexpr void assign(size_type n, const T& val)    {        clear();        resize(n, val);    }    // TODO: check whether InputIter satisfies LegacyInputIterator    template <typename InputIter>    constexpr void assign(InputIter first, InputIter last)    {        clear();        insert(cbegin(), first, last);    }    constexpr void assign(std::initializer_list<T> init)    {        clear();        insert(cbegin(), init.begin(), init.end());    }    constexpr allocator_type get_allocator(void) const noexcept    { return m_alloc; }    constexpr reference at(size_type pos)    {        // TODO: exceptions        // if (pos >= sz)        //     throw std::out_of_range("vector::at");        return m_data[pos];    }    constexpr const_reference at(size_type pos) const    {        // TODO: exceptions        // if (pos >= sz)        //     throw std::out_of_range("vector::at");        return m_data[pos];    }    constexpr reference operator[](size_type pos) noexcept    { return m_data[pos]; }    constexpr const_reference operator[](size_type pos) const noexcept    { return m_data[pos]; }    constexpr reference front() noexcept    { return m_data[0]; }    constexpr const_reference front() const noexcept    { return m_data[0]; }    constexpr reference back() noexcept    { return m_data[m_size - 1]; }    constexpr const_reference back() const noexcept    { return m_data[m_size - 1]; }    constexpr T* data(void) noexcept    { return m_data; }    constexpr const T* data(void) const noexcept    { return m_data; }    // TODO: std::reverse_iterator    constexpr iterator begin() noexcept    { return iterator { m_data }; }    constexpr const_iterator begin() const noexcept    { return const_iterator { m_data }; }    constexpr const_iterator cbegin() const noexcept    { return const_iterator { m_data }; }    constexpr iterator end() noexcept    { return iterator { m_data + m_size }; }    constexpr const_iterator end() const noexcept    { return const_iterator { m_data + m_size }; }    constexpr const_iterator cend() const noexcept    { return const_iterator { m_data + m_size }; }    [[nodiscard]] constexpr bool empty() const noexcept    { return m_size == 0; }    constexpr size_type size() const noexcept    { return m_size; }    constexpr size_type capacity() const noexcept    { return m_capacity; }    constexpr void reserve(size_type new_cap)    {        if (new_cap > m_capacity)            _reallocate_safe(new_cap);    }    constexpr void resize(size_type n)    {        _pre_resize(n);        while (n > m_size)            emplace_back();    }    constexpr void resize(size_type n, const value_type& value)    {        _pre_resize(n);        while (n > m_size)            emplace_back(value);    }    constexpr void shrink_to_fit()    {        if (m_size != m_capacity)            _reallocate_safe(m_size);    }    constexpr void clear() noexcept    { resize(0); }    template <typename... Args>    constexpr iterator emplace(const_iterator pos, Args&&... args)    {        size_type idx = pos - m_data;        if (!pos)            reserve(1);        if (m_size == m_capacity)            reserve(m_capacity * 2);        for (size_type i = m_size; i > idx; --i)            alloc_traits::construct(m_alloc, m_data + i, std::move(m_data[i-1]));        alloc_traits::construct(m_alloc, m_data + idx,            std::forward<Args>(args)...);        ++m_size;        return iterator { m_data + idx };    }    constexpr iterator insert(const_iterator pos, T&& val)    { return emplace(pos, std::move(val)); }    constexpr iterator insert(const_iterator pos, const T& val)    { return emplace(pos, val); }    constexpr iterator insert(const_iterator pos, size_type n, const T& val)    {        if (!n)            return pos;        size_type idx = pos - m_data;        if (!pos)            reserve(n);        if (m_size + n > m_capacity)            reserve(m_size + n);        for (size_type i = m_size + n - 1; i >= idx + n; --i)            alloc_traits::construct(m_alloc, m_data + i, std::move(m_data[i-n]));        for (size_type i = idx; i < idx + n; ++i)            alloc_traits::construct(m_alloc, m_data + i, val);        m_size += n;        return iterator { m_data + idx };    }    // TODO: LegacyInputIterator version of this    template <typename ForwardIter>    constexpr iterator insert(const_iterator pos,        ForwardIter first, ForwardIter last)    {        size_type idx = pos - m_data;        size_type n = 0;        ForwardIter tmp = first;        while (tmp != last)            ++n, ++tmp;        if (!n)            return pos;        if (!pos)            reserve(n);        if (m_size + n > m_capacity)            reserve(m_size + n);        for (size_type i = m_size + n - 1; i >= idx + n; --i)            alloc_traits::construct(m_alloc, m_data + i, std::move(m_data[i-n]));        for (size_type i = idx; i < idx + n; ++i)            alloc_traits::construct(m_alloc, m_data + i, *first++);        m_size += n;        return iterator { m_data + idx };    }    constexpr iterator insert(const_iterator pos, std::initializer_list<T> init)    { return insert(pos, init.begin(), init.end()); }    constexpr iterator erase(const_iterator pos)    {        size_type idx = pos - m_data;        alloc_traits::destroy(m_alloc, m_data + idx);        for (size_type i = idx; i < m_size - 1; ++i)            alloc_traits::construct(m_alloc, m_data + i, std::move(m_data[i+1]));        --m_size;        return iterator { m_data + idx };    }    constexpr iterator erase(const_iterator first, const_iterator last)    {        size_type n = last - first;        if (!n)            return last;        size_type idx = first - m_data;        for (size_type i = idx; i < idx + n; ++i)            alloc_traits::destroy(m_alloc, m_data + i);        for (size_type i = idx; i < m_size - n; ++i)            m_alloc.construct(m_data + i, std::move(m_data[i+n]));        m_size -= n;        return iterator { m_data + idx };    }    constexpr void push_back(const T& val) { insert(cend(), val); }    constexpr void push_back(T&& val) { insert(cend(), std::move(val)); }    template <typename... Args>    constexpr void emplace_back(Args&&... args)    { emplace(cend(), std::forward<Args>(args)...); }    constexpr void pop_back() { erase(--cend()); }    constexpr void swap(vector& other) noexcept(        alloc_traits::propagate_on_container_swap::value        || alloc_traits::is_always_equal::value)    {        if (alloc_traits::propagate_on_container_swap::value)            std::swap(m_alloc, other.m_alloc);        std::swap(m_data, other.m_data);        std::swap(m_size, other.m_size);        std::swap(m_capacity, other.m_capacity);    }};template <typename T, typename Allocator>constexpr void swap(    std::vector<T, Allocator>& lhs,    std::vector<T, Allocator>& rhs) noexcept(noexcept(lhs.swap(rhs))){ lhs.swap(rhs); }template <typename T, typename Allocator, typename U>constexpr typename std::vector<T, Allocator>::size_typeerase(std::vector<T, Allocator>& vec, const U& value){    typename std::vector<T, Allocator>::size_type n = 0;    for (auto iter = vec.begin(); iter != vec.end(); ) {        if (*iter == value) {            iter = vec.erase(iter);            ++n;        } else {            ++iter;        }    }    return n;}template <typename T, typename Allocator, typename Pred>constexpr typename std::vector<T, Allocator>::size_typeerase_if(std::vector<T, Allocator>& vec, Pred pred){    typename std::vector<T, Allocator>::size_type n = 0;    for (auto iter = vec.begin(); iter != vec.end(); ) {        if (pred(*iter)) {            iter = vec.erase(iter);            ++n;        } else {            ++iter;        }    }    return n;}} // namespace std#endif
 |