/** This file is a part of rexy's general purpose library Copyright (C) 2020 rexy712 This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef REXY_CX_VECTOR_HPP #define REXY_CX_VECTOR_HPP #include //size_t #include //move, forward #include "detail/bool_specialize_base.hpp" #include "../utility.hpp" //swap #include "../compat/standard.hpp" #include namespace rexy::cx{ template class vector { public: using value_type = T; using size_type = std::size_t; using difference_type = ptrdiff_t; using iterator = T*; using const_iterator = const T*; using reference = T&; using const_reference = const T&; using pointer = T*; using const_pointer = const T*; static constexpr size_type max_elements = N; private: value_type m_elements[N] = {}; size_type m_size = 0; public: constexpr vector(void)noexcept(std::is_nothrow_default_constructible::value) = default; constexpr vector(const vector&)noexcept(std::is_nothrow_copy_constructible::value) = default; constexpr vector(vector&&)noexcept(std::is_nothrow_move_constructible::value) = default; constexpr vector(size_type count, const T& value) noexcept(std::is_nothrow_copy_assignable::value) { for(size_type i = 0;i < min(count, max_elements);++i){ m_elements[i] = value; } m_size = min(count, max_elements); } REXY_CPP20_CONSTEXPR ~vector(void)noexcept = default; constexpr vector& operator=(const vector&)noexcept(std::is_nothrow_copy_assignable::value) = default; constexpr vector& operator=(vector&&)noexcept(std::is_nothrow_move_assignable::value) = default; constexpr reference at(size_type pos)noexcept{ return m_elements[pos]; } constexpr const_reference at(size_type pos)const noexcept{ return m_elements[pos]; } constexpr reference operator[](size_type pos)noexcept{ return m_elements[pos]; } constexpr const_reference operator[](size_type pos)const noexcept{ return m_elements[pos]; } constexpr reference front(void)noexcept{ return m_elements[0]; } constexpr const_reference front(void)const noexcept{ return m_elements[0]; } constexpr reference back(void)noexcept{ return m_elements[m_size-1]; } constexpr const_reference back(void)const noexcept{ return m_elements[m_size-1]; } constexpr const_pointer data(void)const noexcept{ return m_elements; } constexpr iterator begin(void)noexcept{ return m_elements; } constexpr const_iterator begin(void)const noexcept{ return m_elements; } constexpr const_iterator cbegin(void)const noexcept{ return m_elements; } constexpr iterator end(void)noexcept{ return m_elements+m_size; } constexpr const_iterator end(void)const noexcept{ return m_elements+m_size; } constexpr const_iterator cend(void)const noexcept{ return m_elements+m_size; } constexpr bool empty(void)const noexcept{ return m_size == 0; } constexpr size_type size(void)const noexcept{ return m_size; } constexpr size_type max_size(void)const noexcept{ return max_elements; } constexpr size_type capacity(void)const noexcept{ return max_elements; } constexpr void clear(void)noexcept{ m_size = 0; } constexpr iterator insert(iterator pos, const T& value) noexcept(std::is_nothrow_move_assignable::value && std::is_nothrow_copy_assignable::value) { auto start = pos; if(start != end()){ auto it = pos; ++pos; for(;pos != end();++it,++pos){ *pos = std::move(*it); } } ++m_size; *start = value; return start; } constexpr iterator insert(const_iterator pos, T&& value) noexcept(std::is_nothrow_move_assignable::value) { auto start = pos; if(start != end()){ auto it = pos; ++pos; for(;pos != end();++it,++pos){ *pos = std::move(*it); } } ++m_size; *start = std::move(value); return begin() + (pos - start); } template constexpr iterator emplace(const_iterator pos, Args&&... args) noexcept(std::is_nothrow_move_assignable::value && std::is_nothrow_constructible::value) { auto start = pos; if(start != end()){ auto it = pos; ++pos; for(;pos != end();++it,++pos){ *pos = std::move(*it); } } ++m_size; *start = T{std::forward(args)...}; return begin() + (start - pos); } constexpr iterator erase(const_iterator pos) noexcept(std::is_nothrow_move_assignable::value) { auto start = pos; if(start != end()){ auto it = pos; ++pos; for(;pos != end();++it,++pos){ *it = std::move(*pos); } } --m_size; return begin() + (end() - start); } constexpr iterator push_back(const T& value) noexcept(std::is_nothrow_copy_assignable::value) { m_elements[m_size] = value; return m_elements+(m_size++); } template constexpr iterator emplace_back(Args&&... args) noexcept(std::is_nothrow_constructible::value) { m_elements[m_size++] = T{std::forward(args)...}; return m_elements+(m_size++); } constexpr void pop_back(void)noexcept{ --m_size; } constexpr void resize(size_type count)noexcept{ if(count <= max_size()) m_size = count; } constexpr void resize(size_type count, const value_type& value)noexcept{ if(count > m_size){ if(count <= max_size()){ for(size_type i = m_size;i < count;++i){ m_elements[i] = value; } } }else{ m_size = count; } } constexpr void fill(const T& value) noexcept(std::is_nothrow_copy_assignable::value) { for(auto it = begin();it != end();++it){ *it = value; } } constexpr void swap(vector& other) noexcept(noexcept(swap(m_elements[0], other.m_elements[0]))) { size_type i = 0; for(;i < m_size;++i){ swap(m_elements[i], other.m_elements[i]); } for(;i < other.m_size;++i){ swap(m_elements[i], other.m_elements[i]); } swap(m_size, other.m_size); } }; template class vector : public detail::bool_specialize_base { public: using value_type = bool; using size_type = bool_specialize_base::size_type; using difference_type = bool_specialize_base::difference_type; using iterator = bool_iter; using const_iterator = const_bool_iter; using reference = boolean; using const_reference = bool; static constexpr size_type max_elements = N; private: static constexpr size_type arr_size = (N / bits_per_byte) + (N % bits_per_byte == 0 ? 0 : 1); size_type m_size = 0; booleans m_elements[arr_size] = {}; public: constexpr vector(void)noexcept = default; constexpr vector(const vector&)noexcept = default; constexpr vector(vector&&)noexcept = default; constexpr vector(size_type count, const value_type& value)noexcept{ auto [byte_count,bits_count] = convert_to_byte_bit_pair(count); size_type i = 0; for(;i < byte_count;++i){ for(size_type j = 0;i < bits_per_byte;++i){ m_elements[i][j] = value; } } for(size_type j = 0;j < bits_count;++j){ m_elements[i][j] = value; } m_size = min(count, max_elements); } REXY_CPP20_CONSTEXPR ~vector(void)noexcept = default; constexpr vector& operator=(const vector&)noexcept = default; constexpr vector& operator=(vector&&)noexcept = default; constexpr reference at(size_type pos)noexcept{ auto [byte_count,bits_count] = convert_to_byte_bit_pair(pos); return m_elements[byte_count][bits_count]; } constexpr const_reference at(size_type pos)const noexcept{ auto [byte_count,bits_count] = convert_to_byte_bit_pair(pos); return m_elements[byte_count][bits_count]; } constexpr reference operator[](size_type pos)noexcept{ auto [byte_count,bits_count] = convert_to_byte_bit_pair(pos); return m_elements[byte_count][bits_count]; } constexpr const_reference operator[](size_type pos)const noexcept{ auto [byte_count,bits_count] = convert_to_byte_bit_pair(pos); return m_elements[byte_count][bits_count]; } constexpr reference front(void)noexcept{ return m_elements[0][0]; } constexpr const_reference front(void)const noexcept{ return m_elements[0][0]; } constexpr reference back(void)noexcept{ if(!m_size) return m_elements[0][0]; auto [byte_count,bits_count] = convert_to_byte_bit_pair(m_size); if(bits_count == 0){ bits_count = bits_per_byte-1; byte_count -= 1; } return m_elements[byte_count][bits_count]; } constexpr const_reference back(void)const noexcept{ if(!m_size) return m_elements[0][0]; auto [byte_count,bits_count] = convert_to_byte_bit_pair(m_size); if(bits_count == 0){ bits_count = bits_per_byte-1; byte_count -= 1; } return m_elements[byte_count][bits_count]; } constexpr iterator begin(void)noexcept{ return bool_iter{m_elements[0], 0}; } constexpr const_iterator begin(void)const noexcept{ return const_bool_iter{m_elements[0], 0}; } constexpr const_iterator cbegin(void)const noexcept{ return const_bool_iter{m_elements[0], 0}; } constexpr iterator end(void)noexcept{ auto [byte_count,bits_count] = convert_to_byte_bit_pair(m_size); return bool_iter{m_elements[byte_count], bits_count}; } constexpr const_iterator end(void)const noexcept{ auto [byte_count,bits_count] = convert_to_byte_bit_pair(m_size); return const_bool_iter{m_elements[byte_count], bits_count}; } constexpr const_iterator cend(void)const noexcept{ auto [byte_count,bits_count] = convert_to_byte_bit_pair(m_size); return const_bool_iter{m_elements[byte_count], bits_count}; } constexpr bool empty(void)const noexcept{ return m_size == 0; } constexpr size_type size(void)const noexcept{ return m_size; } constexpr size_type max_size(void)const noexcept{ return max_elements; } constexpr size_type capacity(void)const noexcept{ return max_elements; } constexpr void clear(void)noexcept{ m_size = 0; } constexpr iterator insert(const_iterator pos, const value_type& value)noexcept{ auto start = pos; if(pos != end()){ auto it = pos; ++pos; for(;pos != end();++it,++pos){ *pos = std::move(*it); } } ++m_size; *start = value; return begin() + (pos - start); } template constexpr iterator emplace(const_iterator pos, Args&&... args)noexcept{ auto start = pos; if(pos != end()){ auto it = pos; ++pos; for(;pos != end();++it,++pos){ *pos = std::move(*it); } } ++m_size; *start = bool{std::forward(args)...}; return begin() + (pos - start); } constexpr iterator erase(const_iterator pos)noexcept{ auto start = pos; if(pos != end()){ auto it = pos; ++pos; for(;pos != end();++it,++pos){ *it = std::move(*pos); } } --m_size; return begin() + (end() - start); } constexpr iterator push_back(const value_type& value)noexcept{ return insert(end(), value); } template constexpr iterator emplace_back(Args&&... args)noexcept{ return emplace(end(), std::forward(args)...); } constexpr void pop_back(void)noexcept{ --m_size; } constexpr void resize(size_type count)noexcept{ if(count <= max_size()) m_size = count; } constexpr void resize(size_type count, const value_type& value)noexcept{ if(count > m_size){ auto actual_count = min(count, max_size()); auto num = actual_count - m_size; auto it = end(); for(size_type i = 0;i < num;++i){ *it = value; ++it; } } m_size = count; } constexpr void fill(const bool& value)noexcept{ for(auto it = begin();it != end();++it){ *it = value; } } constexpr void swap(vector& other)noexcept{ auto [byte_count,bits_count] = convert_to_byte_bit_pair(m_size); auto [other_byte_count,other_bits_count] = convert_to_byte_bit_pair(other.m_size); if(bits_count) ++byte_count; if(other_bits_count) ++other_byte_count; size_type i = 0; for(;i < byte_count;++i){ swap(m_elements[i], other.m_elements[i]); } for(;i < other_byte_count;++i){ swap(m_elements[i], other.m_elements[i]); } swap(m_size, other.m_size); } }; } #endif