added first version of methods
This commit is contained in:
parent
b368102f1f
commit
b3a062688e
|
|
@ -54,6 +54,8 @@ namespace cc {
|
|||
constexpr const_vector(const const_vector& other) noexcept;
|
||||
constexpr const_vector(const_vector&& other) noexcept;
|
||||
|
||||
constexpr ~const_vector() = default; // elements in static array should be destroyed automatically
|
||||
|
||||
constexpr const_vector<T, N>& operator=(const const_vector& other);
|
||||
constexpr const_vector<T, N>& operator=(const_vector&& other) noexcept;
|
||||
constexpr const_vector<T, N>& operator=(const value_type (&array)[N]) noexcept;
|
||||
|
|
@ -66,6 +68,9 @@ namespace cc {
|
|||
constexpr reference at(size_type pos);
|
||||
constexpr const_reference at(size_type pos) const;
|
||||
|
||||
constexpr T& operator[](size_type pos) { return _arr[pos]; }
|
||||
constexpr const T& operator[](size_type pos) const { return _arr[pos]; }
|
||||
|
||||
[[nodiscard]] constexpr reference front() noexcept{ return _arr[0]; }
|
||||
[[nodiscard]] constexpr const_reference front() const noexcept { return _arr[0]; }
|
||||
|
||||
|
|
@ -76,21 +81,54 @@ namespace cc {
|
|||
[[nodiscard]] constexpr const value_type * data() const noexcept { return _arr; }
|
||||
|
||||
[[nodiscard]] constexpr iterator begin() noexcept { return _arr; };
|
||||
[[nodiscard]] constexpr const_iterator begin() const noexcept { return _arr; };
|
||||
[[nodiscard]] constexpr const_iterator cbegin() const noexcept { return _arr; };
|
||||
|
||||
[[nodiscard]] constexpr iterator end() noexcept { return _arr + _size; };
|
||||
[[nodiscard]] constexpr const_iterator end() const noexcept { return _arr + _size; };
|
||||
[[nodiscard]] constexpr const_iterator cend() const noexcept { return _arr + _size; };
|
||||
|
||||
[[nodiscard]] constexpr reverse_iterator rbegin() noexcept { return std::reverse_iterator<iterator>(_arr + _size); };
|
||||
[[nodiscard]] constexpr const_reverse_iterator rbegin() const noexcept { return std::reverse_iterator<const_iterator>(_arr + _size); };
|
||||
[[nodiscard]] constexpr const_reverse_iterator crbegin() const noexcept { return std::reverse_iterator<const_iterator>(_arr + _size); };
|
||||
|
||||
[[nodiscard]] constexpr reverse_iterator rend() noexcept { return std::reverse_iterator<iterator>(_arr); };
|
||||
[[nodiscard]] constexpr const_reverse_iterator rend() const noexcept { return std::reverse_iterator<const_iterator>(_arr); };
|
||||
[[nodiscard]] constexpr const_reverse_iterator crend() const noexcept { return std::reverse_iterator<const_iterator>(_arr); };
|
||||
|
||||
[[nodiscard]] constexpr bool empty() const noexcept { return begin() == end(); } // vector standard defines empty as this
|
||||
[[nodiscard]] constexpr size_type max_size() const noexcept { return _len; }
|
||||
[[nodiscard]] constexpr size_type capacity() const noexcept { return _len; }
|
||||
[[nodiscard]] constexpr size_type size() const noexcept { return _size; }
|
||||
|
||||
constexpr T& operator[](size_type pos) { return _arr[pos]; }
|
||||
constexpr const T& operator[](size_type pos) const { return _arr[pos]; }
|
||||
constexpr void clear() { _erase_no_move(std::begin(_arr), std::end(_arr)); }
|
||||
|
||||
constexpr iterator insert(const_iterator pos, const T& value);
|
||||
constexpr iterator insert(const_iterator pos, T&& value);
|
||||
constexpr iterator insert(const_iterator pos, size_type count, const T& value);
|
||||
template<std::input_iterator InputIt>
|
||||
constexpr iterator insert(const_iterator pos, InputIt first, InputIt last);
|
||||
constexpr iterator insert(const_iterator pos, std::initializer_list<T> values);
|
||||
|
||||
template<typename ...Args>
|
||||
constexpr iterator emplace(const_iterator pos, Args&&... args);
|
||||
|
||||
constexpr iterator erase(const_iterator pos);
|
||||
constexpr iterator erase(const_iterator first, const_iterator last);
|
||||
|
||||
constexpr void push_back(const T& value);
|
||||
constexpr void push_back(T&& value);
|
||||
|
||||
template<typename ...Args>
|
||||
constexpr reference emplace_back(Args&&... args);
|
||||
|
||||
constexpr void pop_back();
|
||||
|
||||
template<std::size_t N2>
|
||||
constexpr void swap(const_vector<T, N2>& other);
|
||||
|
||||
protected:
|
||||
constexpr inline void _erase_no_move(const_iterator first, const_iterator last) { std::destroy(first, last); }
|
||||
|
||||
#ifdef UNIT_TEST
|
||||
friend test_const_vector;
|
||||
|
|
@ -105,6 +143,47 @@ namespace cc {
|
|||
const_vector(T...) -> const_vector<std::common_type_t<T...>, sizeof...(T)>;
|
||||
|
||||
|
||||
template<typename T1, typename T2, std::size_t N1, std::size_t N2>
|
||||
constexpr bool operator==(const const_vector<T1, N1>& lhs,
|
||||
const const_vector<T2, N2>& rhs)
|
||||
{
|
||||
return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin());
|
||||
}
|
||||
|
||||
template<typename T1, typename T2, std::size_t N1, std::size_t N2>
|
||||
constexpr auto operator<=>(const const_vector<T1, N1>& lhs,
|
||||
const const_vector<T2, N2>& rhs)
|
||||
{
|
||||
return std::lexicographical_compare_three_way(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), std::compare_three_way());
|
||||
}
|
||||
|
||||
template<typename T, std::size_t N1, std::size_t N2>
|
||||
constexpr void swap(const const_vector<T, N1>& lhs,
|
||||
const const_vector<T, N2>& rhs)
|
||||
{
|
||||
return lhs.swap(rhs);
|
||||
}
|
||||
|
||||
template<typename T, std::size_t N, typename U>
|
||||
constexpr const_vector<T, N>::size_type erase(const_vector<T, N>& vec, const U& value)
|
||||
{
|
||||
auto it = std::remove(vec.begin(), vec.end(), value);
|
||||
auto r = vec.end() - it;
|
||||
vec.erase(it, vec.end());
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
template<typename T, std::size_t N, typename Pred>
|
||||
constexpr const_vector<T, N>::size_type erase(const_vector<T, N>& vec, Pred pred)
|
||||
{
|
||||
auto it = std::remove_if(vec.begin(), vec.end(), pred);
|
||||
auto r = vec.end() - it;
|
||||
vec.erase(it, vec.end());
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
template<typename T, std::size_t N>
|
||||
constexpr const_vector<T, N>::const_vector(const value_type &value) noexcept
|
||||
|
|
@ -137,21 +216,26 @@ namespace cc {
|
|||
|
||||
template<typename T, std::size_t N>
|
||||
template<std::input_iterator InputIt>
|
||||
constexpr const_vector<T, N>::const_vector(InputIt first, InputIt last) {
|
||||
constexpr const_vector<T, N>::const_vector(InputIt first, InputIt last)
|
||||
: _size(std::distance(first, last)) {
|
||||
//static_assert(std::distance(first, last) > N, "tried inserting more elements than const_vector is in size");
|
||||
_size = std::distance(first, last);
|
||||
std::copy(first, last, _arr);
|
||||
}
|
||||
|
||||
template<typename T, std::size_t N>
|
||||
constexpr const_vector<T, N>::const_vector(const const_vector &other) noexcept {
|
||||
static_assert(N >= other._size, "size of other has to be equal to or smaller than this");
|
||||
constexpr const_vector<T, N>::const_vector(const const_vector &other) noexcept
|
||||
: _size(other._size)
|
||||
{
|
||||
if (N >= other._size) throw std::invalid_argument("size of other has to be equal to or smaller than this");
|
||||
std::copy(other._arr, other._arr, _arr);
|
||||
}
|
||||
|
||||
template<typename T, std::size_t N>
|
||||
constexpr const_vector<T, N>::const_vector(const_vector &&other) noexcept {
|
||||
static_assert(N == other.N, "size of const_vectors does not match");
|
||||
constexpr const_vector<T, N>::const_vector(const_vector &&other) noexcept
|
||||
: _size(other._size)
|
||||
{
|
||||
static_assert(N == other._len, "size of const_vectors does not match");
|
||||
std::move(other.begin(), other.end(), _arr);
|
||||
}
|
||||
|
||||
|
|
@ -171,9 +255,11 @@ namespace cc {
|
|||
constexpr const_vector<T, N> &const_vector<T, N>::operator=(const_vector &&other) noexcept
|
||||
{
|
||||
static_assert(N == other._len, "Cannot assign const_vector to other with different size");
|
||||
if (N != other.N) throw std::exception();
|
||||
if (N != other._len) throw std::exception();
|
||||
|
||||
clear();
|
||||
std::move(other.begin(), other.end(), _arr);
|
||||
_size = other._size;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
|
@ -186,23 +272,28 @@ namespace cc {
|
|||
}
|
||||
|
||||
template<typename T, std::size_t N>
|
||||
constexpr void const_vector<T, N>::assign(const_vector::size_type count, const value_type &value) noexcept {
|
||||
constexpr void const_vector<T, N>::assign(const_vector::size_type count, const value_type &value) noexcept
|
||||
{
|
||||
if (count > N) count = N;
|
||||
_size = count;
|
||||
|
||||
std::fill(std::begin(_arr), std::end(_arr), value);
|
||||
}
|
||||
|
||||
template<typename T, std::size_t N>
|
||||
template<std::input_iterator InputIt>
|
||||
constexpr void const_vector<T, N>::assign(InputIt first, InputIt last) {
|
||||
constexpr void const_vector<T, N>::assign(InputIt first, InputIt last)
|
||||
{
|
||||
auto distance = std::distance(first, last);
|
||||
if (distance > N) throw std::invalid_argument("Iterator distance in assign surpasses size" + std::to_string(distance) + ">=" + std::to_string(N));
|
||||
_size = distance;
|
||||
std::destroy(_arr, _arr + _size);
|
||||
std::copy(first, last, _arr);
|
||||
}
|
||||
|
||||
template<typename T, std::size_t N>
|
||||
constexpr void const_vector<T, N>::assign(std::initializer_list<value_type> values) {
|
||||
constexpr void const_vector<T, N>::assign(std::initializer_list<value_type> values)
|
||||
{
|
||||
auto values_size = std::distance(values.begin(), values.end());
|
||||
if (values_size > N) throw std::invalid_argument("Initializer list in assign has more elements than size" + std::to_string(values_size) + ">=" + std::to_string(N));
|
||||
_size = values_size;
|
||||
|
|
@ -210,17 +301,157 @@ namespace cc {
|
|||
}
|
||||
|
||||
template<typename T, std::size_t N>
|
||||
constexpr const_vector<T, N>::reference const_vector<T, N>::at(const_vector::size_type pos) {
|
||||
constexpr const_vector<T, N>::reference const_vector<T, N>::at(const_vector::size_type pos)
|
||||
{
|
||||
if (pos >= _size) throw std::out_of_range("Pos " + std::to_string(pos) + " is out of range");
|
||||
return _arr[pos];
|
||||
}
|
||||
|
||||
template<typename T, std::size_t N>
|
||||
constexpr const_vector<T, N>::const_reference const_vector<T, N>::at(const_vector::size_type pos) const {
|
||||
constexpr const_vector<T, N>::const_reference const_vector<T, N>::at(const_vector::size_type pos) const
|
||||
{
|
||||
if (pos >= _size) throw std::out_of_range("Pos " + std::to_string(pos) + " is out of range");
|
||||
return _arr[pos];
|
||||
}
|
||||
|
||||
template<typename T, std::size_t N>
|
||||
constexpr const_vector<T, N>::iterator const_vector<T, N>::insert(const_vector::const_iterator pos, const T &value)
|
||||
{
|
||||
if (_size == N) throw std::exception();
|
||||
|
||||
ptrdiff_t i = pos - _arr;
|
||||
std::move(_arr + i, _arr + _size, _arr + i + 1);
|
||||
_arr[i] = value;
|
||||
|
||||
++_size;
|
||||
return pos;
|
||||
}
|
||||
|
||||
template<typename T, std::size_t N>
|
||||
constexpr const_vector<T, N>::iterator const_vector<T, N>::insert(const_vector::const_iterator pos, T &&value)
|
||||
{
|
||||
if (_size == N) throw std::exception();
|
||||
|
||||
ptrdiff_t i = pos - _arr;
|
||||
std::move(_arr + i, _arr + _size, _arr + i + 1);
|
||||
_arr[i] = std::move(value);
|
||||
|
||||
++_size;
|
||||
return pos;
|
||||
}
|
||||
|
||||
template<typename T, std::size_t N>
|
||||
constexpr const_vector<T, N>::iterator
|
||||
const_vector<T, N>::insert(const_vector::const_iterator pos, const_vector::size_type count, const T &value)
|
||||
{
|
||||
if (count == 0) return pos;
|
||||
if (_size + count >= N) throw std::exception();
|
||||
|
||||
std::move(pos, _arr + _size, pos + count);
|
||||
std::fill(pos, pos + count, value);
|
||||
|
||||
_size += count;
|
||||
return pos;
|
||||
}
|
||||
|
||||
template<typename T, std::size_t N>
|
||||
template<std::input_iterator InputIt>
|
||||
constexpr const_vector<T, N>::iterator
|
||||
const_vector<T, N>::insert(const_vector::const_iterator pos, InputIt first, InputIt last)
|
||||
{
|
||||
auto count = std::distance(first, last);
|
||||
|
||||
if (first == last) return pos;
|
||||
if (_size + count >= N) throw std::exception();
|
||||
|
||||
|
||||
std::move(pos, _arr + _size, pos + count);
|
||||
std::copy(first, last, pos);
|
||||
|
||||
_size += count;
|
||||
return pos;
|
||||
}
|
||||
|
||||
template<typename T, std::size_t N>
|
||||
constexpr const_vector<T, N>::iterator
|
||||
const_vector<T, N>::insert(const_vector::const_iterator pos, std::initializer_list<T> values)
|
||||
{
|
||||
return insert(pos, values.begin(), values.end());
|
||||
}
|
||||
|
||||
template<typename T, std::size_t N>
|
||||
template<class... Args>
|
||||
constexpr const_vector<T, N>::iterator const_vector<T, N>::emplace(const_vector::const_iterator pos, Args &&... args)
|
||||
{
|
||||
if (_size == N) throw std::exception();
|
||||
|
||||
T obj(std::forward<Args>(args)...);
|
||||
|
||||
ptrdiff_t i = pos - _arr;
|
||||
std::move(_arr + i, _arr + _size, _arr + i + 1);
|
||||
_erase_no_move(pos);
|
||||
_arr[i] = std::move(obj);
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
template<typename T, std::size_t N>
|
||||
constexpr const_vector<T, N>::iterator const_vector<T, N>::erase(const_vector::const_iterator pos)
|
||||
{
|
||||
_erase_no_move(pos);
|
||||
std::move(pos + 1, end(), pos);
|
||||
--_size;
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
template<typename T, std::size_t N>
|
||||
constexpr const_vector<T, N>::iterator
|
||||
const_vector<T, N>::erase(const_vector::const_iterator first, const_vector::const_iterator last)
|
||||
{
|
||||
_erase_no_move(first, last);
|
||||
std::move(last + 1, end(), first);
|
||||
_size -= (last - first);
|
||||
|
||||
return first;
|
||||
}
|
||||
|
||||
template<typename T, std::size_t N>
|
||||
constexpr void const_vector<T, N>::push_back(const const_vector::value_type &value)
|
||||
{
|
||||
insert(end(), value);
|
||||
}
|
||||
|
||||
template<typename T, std::size_t N>
|
||||
constexpr void const_vector<T, N>::push_back(T&& value)
|
||||
{
|
||||
insert(end(), value);
|
||||
}
|
||||
|
||||
template<typename T, std::size_t N>
|
||||
template<typename ...Args>
|
||||
constexpr const_vector<T, N>::reference const_vector<T, N>::emplace_back(Args&&... args)
|
||||
{
|
||||
emplace(end(), std::forward(args)...);
|
||||
}
|
||||
|
||||
template<typename T, std::size_t N>
|
||||
constexpr void const_vector<T, N>::pop_back()
|
||||
{
|
||||
_erase_no_move(end() - 1, end());
|
||||
--_size;
|
||||
}
|
||||
|
||||
template<typename T, std::size_t N>
|
||||
template<std::size_t N2>
|
||||
constexpr void const_vector<T, N>::swap(const_vector<T, N2> &other)
|
||||
{
|
||||
if (_size > other._len || other._size > N) throw std::exception();
|
||||
|
||||
cc::helper::swap_iter_range(begin(), end(), std::end(_arr), other.begin(), other.end(), std::end(other._arr));
|
||||
std::swap(_size, other._size);
|
||||
}
|
||||
|
||||
}; // cc
|
||||
|
||||
#endif //UDIFF_IMMARRAY_H_
|
||||
|
|
|
|||
|
|
@ -9,9 +9,58 @@
|
|||
|
||||
namespace cc::helper {
|
||||
|
||||
template <std::input_or_output_iterator Iter, typename Distance>
|
||||
inline auto advanced(Iter i, Distance n) { std::advance(i, n); return i; }
|
||||
|
||||
template<typename T, std::size_t N>
|
||||
constexpr std::size_t array_size(const T(&)[N]) { return N; }
|
||||
|
||||
template<std::input_or_output_iterator InputIt1, std::input_or_output_iterator InputIt2, typename T = InputIt1::value_type>
|
||||
requires ((InputIt1::value_type == InputIt2::value_type)
|
||||
&& std::indirectly_writable<typename InputIt1::value_type, InputIt1> && std::indirectly_readable<InputIt1>
|
||||
&& std::indirectly_writable<typename InputIt2::value_type, InputIt1> && std::indirectly_readable<InputIt2>)
|
||||
constexpr void swap_iter_range(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2)
|
||||
{
|
||||
auto dist1 = std::distance(first1, last1);
|
||||
auto dist2 = std::distance(first2, last2);
|
||||
|
||||
if (dist1 == dist2) {
|
||||
std::swap_ranges(first1, last1, first2);
|
||||
return;
|
||||
}
|
||||
|
||||
auto swap_dist = std::min(dist1, dist2);
|
||||
|
||||
std::swap_ranges(first1, advanced(first1, swap_dist), first2, advanced(first2, swap_dist));
|
||||
|
||||
std::advance(first1, swap_dist);
|
||||
std::advance(first2, swap_dist);
|
||||
|
||||
if (dist1 < dist2) {
|
||||
std::move(first2, last2, last1);
|
||||
} else {
|
||||
std::move(first1, last1, last2);
|
||||
}
|
||||
}
|
||||
|
||||
template<std::input_or_output_iterator InputIt1, std::input_or_output_iterator InputIt2, typename T = InputIt1::value_type>
|
||||
requires ((InputIt1::value_type == InputIt2::value_type)
|
||||
&& std::indirectly_writable<typename InputIt1::value_type, InputIt1> && std::indirectly_readable<InputIt1>
|
||||
&& std::indirectly_writable<typename InputIt2::value_type, InputIt1> && std::indirectly_readable<InputIt2>)
|
||||
constexpr void swap(InputIt1 first1, InputIt1 last1, InputIt1 end1, InputIt2 first2, InputIt2 last2, InputIt2 end2)
|
||||
{
|
||||
auto max_dist = std::min(std::distance(first1, end1), std::distance(first2, end2));
|
||||
|
||||
auto dist1 = std::distance(first1, last1);
|
||||
auto dist2 = std::distance(first2, last2);
|
||||
|
||||
if (max_dist < dist1 || max_dist < dist2) throw std::invalid_argument("Distance between iterators does not fit inbetween other "
|
||||
"(Range 1: " + std::to_string(dist1) + "/" + std::to_string(std::distance(first1, end1)) + ", " +
|
||||
"Range 2: " + std::to_string(dist2) + "/" + std::to_string(std::distance(first2, end2)) + ")");
|
||||
|
||||
swap_iter_range(first1, last1, first2, last2);
|
||||
}
|
||||
|
||||
}; // cc
|
||||
|
||||
#endif //UDIFF_HELPER_H_
|
||||
|
|
|
|||
Loading…
Reference in New Issue