|  | @@ -0,0 +1,483 @@
 | 
	
		
			
				|  |  | +#ifndef __GBLIBCPP_VECTOR__
 | 
	
		
			
				|  |  | +#define __GBLIBCPP_VECTOR__
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#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 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)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        auto* newptr = alloc_traits::allocate(m_alloc, n);
 | 
	
		
			
				|  |  | +        for (size_t i = 0; i < m_size; ++i) {
 | 
	
		
			
				|  |  | +            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();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    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;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    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;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    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_capacity * 2);
 | 
	
		
			
				|  |  | +        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_capacity * 2);
 | 
	
		
			
				|  |  | +        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_type
 | 
	
		
			
				|  |  | +erase(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_type
 | 
	
		
			
				|  |  | +erase_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
 |