341 lines
		
	
	
		
			8.0 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			341 lines
		
	
	
		
			8.0 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
 | 
						|
#pragma once
 | 
						|
 | 
						|
#if !defined(BAD_APPLE_OS_VECTOR_INCLUDED)
 | 
						|
#define BAD_APPLE_OS_VECTOR_INCLUDED
 | 
						|
 | 
						|
#include <algorithm>
 | 
						|
#include <cstddef>
 | 
						|
#include <memory>
 | 
						|
#include <new>
 | 
						|
#include <stdexcept>
 | 
						|
#include <utility>
 | 
						|
 | 
						|
namespace std
 | 
						|
{
 | 
						|
template<typename T, typename Allocator = allocator<T>>
 | 
						|
class vector
 | 
						|
{
 | 
						|
public:
 | 
						|
    using value_type = T;
 | 
						|
    using size_type = size_t;
 | 
						|
    using difference_type = ptrdiff_t;
 | 
						|
    using reference = value_type&;
 | 
						|
    using const_reference = const value_type&;
 | 
						|
    using pointer = value_type*;
 | 
						|
    using const_pointer = const value_type*;
 | 
						|
    using iterator = pointer;
 | 
						|
    using const_iterator = const_pointer;
 | 
						|
private:
 | 
						|
    T* _elements = nullptr;
 | 
						|
    size_type _size = 0;
 | 
						|
    size_type _capacity = 0;
 | 
						|
    Allocator _allocator = {};
 | 
						|
public:
 | 
						|
    constexpr vector() noexcept = default;
 | 
						|
    constexpr vector(const vector& other) noexcept : _allocator(other._allocator)
 | 
						|
    {
 | 
						|
        resize(other.size());
 | 
						|
        for (size_type idx = 0; idx < size(); ++idx)
 | 
						|
        {
 | 
						|
            (*this)[idx] = other[idx];
 | 
						|
        }
 | 
						|
    }
 | 
						|
    constexpr vector(vector&& other) noexcept
 | 
						|
        : _elements(exchange(other._elements, nullptr)),
 | 
						|
          _size(exchange(other._size, 0)),
 | 
						|
          _capacity(exchange(other._capacity, 0)),
 | 
						|
          _allocator(exchange(other._allocator, {}))
 | 
						|
    {
 | 
						|
    }
 | 
						|
    constexpr explicit vector(const Allocator& allocator) noexcept : _allocator(allocator) {}
 | 
						|
    constexpr explicit vector(size_type count, const value_type& value = value_type(), const Allocator& allocator = {}) : _allocator(allocator)
 | 
						|
    {
 | 
						|
        resize(count, value);
 | 
						|
    }
 | 
						|
    constexpr ~vector() noexcept
 | 
						|
    {
 | 
						|
        for (size_type idx = 0; idx < size(); ++idx)
 | 
						|
        {
 | 
						|
            _elements[idx].~T();
 | 
						|
        }
 | 
						|
        _allocator.deallocate(_elements, _capacity);
 | 
						|
    }
 | 
						|
    constexpr vector& operator=(const vector& other)
 | 
						|
    {
 | 
						|
        if (this == &other) {
 | 
						|
            return *this;
 | 
						|
        }
 | 
						|
        resize(other.size());
 | 
						|
        for (size_type idx = 0; idx < size(); ++idx)
 | 
						|
        {
 | 
						|
            (*this)[idx] = other[idx];
 | 
						|
        }
 | 
						|
        return *this;
 | 
						|
    }
 | 
						|
    constexpr vector& operator=(vector&& other)
 | 
						|
    {
 | 
						|
        if (this == &other) {
 | 
						|
            return *this;
 | 
						|
        }
 | 
						|
        clear();
 | 
						|
        _elements = exchange(other._elements, nullptr);
 | 
						|
        _size = exchange(other._size, 0);
 | 
						|
        _capacity = exchange(other._capacity, 0);
 | 
						|
        return *this;
 | 
						|
    }
 | 
						|
 | 
						|
    [[nodiscard]] constexpr reference operator[](size_type pos) noexcept
 | 
						|
    {
 | 
						|
        return _elements[pos];
 | 
						|
    }
 | 
						|
 | 
						|
    [[nodiscard]] constexpr const_reference operator[](size_type pos) const noexcept
 | 
						|
    {
 | 
						|
        return _elements[pos];
 | 
						|
    }
 | 
						|
 | 
						|
    [[nodiscard]] constexpr reference at(size_type pos)
 | 
						|
    {
 | 
						|
        if (pos >= size()) {
 | 
						|
            __ba_throw out_of_range();
 | 
						|
        }
 | 
						|
        return _elements[pos];
 | 
						|
    }
 | 
						|
 | 
						|
    [[nodiscard]] constexpr const_reference at(size_type pos) const
 | 
						|
    {
 | 
						|
        if (pos >= size()) {
 | 
						|
            __ba_throw out_of_range();
 | 
						|
        }
 | 
						|
        return _elements[pos];
 | 
						|
    }
 | 
						|
 | 
						|
    [[nodiscard]] constexpr reference front() noexcept
 | 
						|
    {
 | 
						|
        return _elements[0];
 | 
						|
    }
 | 
						|
 | 
						|
    [[nodiscard]] constexpr const_reference front() const noexcept
 | 
						|
    {
 | 
						|
        return _elements[0];
 | 
						|
    }
 | 
						|
 | 
						|
    [[nodiscard]] constexpr reference back() noexcept
 | 
						|
    {
 | 
						|
        return _elements[size() - 1];
 | 
						|
    }
 | 
						|
 | 
						|
    [[nodiscard]] constexpr const_reference back() const noexcept
 | 
						|
    {
 | 
						|
        return _elements[size() - 1];
 | 
						|
    }
 | 
						|
 | 
						|
    [[nodiscard]] constexpr pointer data() noexcept
 | 
						|
    {
 | 
						|
        return _elements;
 | 
						|
    }
 | 
						|
 | 
						|
    [[nodiscard]] constexpr const_pointer data() const noexcept
 | 
						|
    {
 | 
						|
        return _elements;
 | 
						|
    }
 | 
						|
 | 
						|
    [[nodiscard]] constexpr iterator begin() noexcept
 | 
						|
    {
 | 
						|
        return _elements;
 | 
						|
    }
 | 
						|
 | 
						|
    [[nodiscard]] constexpr const_iterator begin() const noexcept
 | 
						|
    {
 | 
						|
        return _elements;
 | 
						|
    }
 | 
						|
 | 
						|
    [[nodiscard]] constexpr const_iterator cbegin() const noexcept
 | 
						|
    {
 | 
						|
        return _elements;
 | 
						|
    }
 | 
						|
 | 
						|
    [[nodiscard]] constexpr iterator end() noexcept
 | 
						|
    {
 | 
						|
        return &_elements[size()];
 | 
						|
    }
 | 
						|
 | 
						|
    [[nodiscard]] constexpr const_iterator end() const noexcept
 | 
						|
    {
 | 
						|
        return &_elements[size()];
 | 
						|
    }
 | 
						|
 | 
						|
    [[nodiscard]] constexpr const_iterator cend() const noexcept
 | 
						|
    {
 | 
						|
        return &_elements[size()];
 | 
						|
    }
 | 
						|
 | 
						|
    [[nodiscard]] constexpr bool empty() const noexcept
 | 
						|
    {
 | 
						|
        return size() == 0;
 | 
						|
    }
 | 
						|
 | 
						|
    [[nodiscard]] constexpr size_type size() const noexcept
 | 
						|
    {
 | 
						|
        return _size;
 | 
						|
    }
 | 
						|
 | 
						|
    [[nodiscard]] constexpr size_type max_size() const noexcept
 | 
						|
    {
 | 
						|
        return size_type(-1);
 | 
						|
    }
 | 
						|
 | 
						|
    constexpr void reserve(size_type newCapacity)
 | 
						|
    {
 | 
						|
        if (newCapacity <= capacity()) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        updateCapacity(newCapacity);
 | 
						|
    }
 | 
						|
 | 
						|
    [[nodiscard]] size_type capacity() const noexcept
 | 
						|
    {
 | 
						|
        return _capacity;
 | 
						|
    }
 | 
						|
 | 
						|
    constexpr void shrink_to_fit()
 | 
						|
    {
 | 
						|
        updateCapacity(size());
 | 
						|
    }
 | 
						|
 | 
						|
    constexpr void clear()
 | 
						|
    {
 | 
						|
        resize(0);
 | 
						|
    }
 | 
						|
 | 
						|
    constexpr void push_back(const value_type& value)
 | 
						|
    {
 | 
						|
        reserve(size() + 1);
 | 
						|
        ::new (&_elements[size()]) T(value);
 | 
						|
        ++_size;
 | 
						|
    }
 | 
						|
 | 
						|
    constexpr void push_back(value_type&& value)
 | 
						|
    {
 | 
						|
        reserve(size() + 1);
 | 
						|
        ::new (&_elements[size()]) T(move(value));
 | 
						|
        ++_size;
 | 
						|
    }
 | 
						|
 | 
						|
    constexpr void pop_back() noexcept
 | 
						|
    {
 | 
						|
        resize(size() - 1);
 | 
						|
    }
 | 
						|
 | 
						|
    template<typename... TArgs>
 | 
						|
    constexpr reference emplace_back(TArgs&&... args)
 | 
						|
    {
 | 
						|
        reserve(size() + 1);
 | 
						|
        ::new (&_elements[size()]) T(forward<TArgs>(args)...);
 | 
						|
        ++_size;
 | 
						|
    }
 | 
						|
 | 
						|
    constexpr void resize(size_type newSize)
 | 
						|
    {
 | 
						|
        if (newSize == size()) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        reserve(newSize);
 | 
						|
 | 
						|
        if (newSize > size())
 | 
						|
        {
 | 
						|
            for (size_type idx = size(); idx < newSize; ++idx)
 | 
						|
            {
 | 
						|
                ::new (&_elements[idx]) T();
 | 
						|
            }
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            for (size_type idx = newSize; idx < size(); ++idx)
 | 
						|
            {
 | 
						|
                _elements[idx].~T();
 | 
						|
            }
 | 
						|
        }
 | 
						|
        _size = newSize;
 | 
						|
    }
 | 
						|
 | 
						|
    constexpr void resize(size_type newSize, const value_type& initValue)
 | 
						|
    {
 | 
						|
        if (newSize == size()) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        reserve(newSize);
 | 
						|
 | 
						|
        if (newSize > size())
 | 
						|
        {
 | 
						|
            for (size_type idx = size(); idx < newSize; ++idx)
 | 
						|
            {
 | 
						|
                ::new (&_elements[idx]) T(initValue);
 | 
						|
            }
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            for (size_type idx = newSize; idx < size(); ++idx)
 | 
						|
            {
 | 
						|
                _elements[idx].~T();
 | 
						|
            }
 | 
						|
        }
 | 
						|
        _size = newSize;
 | 
						|
    }
 | 
						|
 | 
						|
    constexpr iterator erase(const_iterator first, const_iterator last)
 | 
						|
    {
 | 
						|
        // the spec wants the parameters to be const iterators...
 | 
						|
        iterator realFirst = begin() + (first - begin());
 | 
						|
        iterator realLast = begin() + (last - begin());
 | 
						|
 | 
						|
        const size_t newSize = size() - (last - first);
 | 
						|
        for (auto it = realLast; it != end(); ++it)
 | 
						|
        {
 | 
						|
            *realFirst = move(*it);
 | 
						|
            ++realFirst;
 | 
						|
        }
 | 
						|
        resize(newSize);
 | 
						|
        return realFirst;
 | 
						|
    }
 | 
						|
 | 
						|
    constexpr iterator erase(const_iterator pos)
 | 
						|
    {
 | 
						|
        return erase(pos, pos + 1);
 | 
						|
    }
 | 
						|
private:
 | 
						|
    void updateCapacity(size_type newCapacity)
 | 
						|
    {
 | 
						|
        if (capacity() == newCapacity) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        T* newElements = _allocator.allocate(newCapacity * sizeof(T));
 | 
						|
        if (newElements == nullptr)
 | 
						|
        {
 | 
						|
            __ba_throw bad_alloc();
 | 
						|
        }
 | 
						|
        for (size_type idx = 0; idx < size(); ++idx)
 | 
						|
        {
 | 
						|
            ::new (&newElements[idx]) T(move(_elements[idx]));
 | 
						|
            _elements[idx].~T();
 | 
						|
        }
 | 
						|
        _allocator.deallocate(_elements, _capacity);
 | 
						|
        _elements = newElements;
 | 
						|
        _capacity = newCapacity;
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
template<typename T, typename TAlloc, typename Pred>
 | 
						|
constexpr vector<T, TAlloc>::size_type erase_if(vector<T, TAlloc>& vec, Pred pred)
 | 
						|
{
 | 
						|
 | 
						|
    auto it = remove_if(vec.begin(), vec.end(), pred);
 | 
						|
    auto removed = vec.end() - it;
 | 
						|
    vec.erase(it, vec.end());
 | 
						|
    return removed;
 | 
						|
}
 | 
						|
}
 | 
						|
 | 
						|
#endif // !defined(BAD_APPLE_OS_VECTOR_INCLUDED)
 |