1#ifndef AOCOMMON_UVECTOR_H_
2#define AOCOMMON_UVECTOR_H_
76template <
typename Tp,
typename Alloc = std::allocator<Tp>>
78 static_assert(std::is_standard_layout<Tp>(),
79 "A UVector can only hold classes with standard layout");
110#if __cplusplus > 201402L
142 std::uninitialized_fill_n<Tp*, size_t>(
_begin, n, val);
150 template <
class InputIterator>
163 : Alloc(
std::allocator_traits<Alloc>::select_on_container_copy_construction(
187 : Alloc(std::move(other)),
191 other._begin =
nullptr;
192 other._end =
nullptr;
193 other._endOfStorage =
nullptr;
205 other._begin =
nullptr;
206 other._end =
nullptr;
207 other._endOfStorage =
nullptr;
220 for (
typename std::initializer_list<Tp>::const_iterator i = initlist.begin();
221 i != initlist.end(); ++i) {
237 other,
typename std::allocator_traits<Alloc>::propagate_on_container_copy_assignment());
246 std::allocator_traits<Alloc>::propagate_on_container_move_assignment::value ||
247 allocator_is_always_equal::value) {
250 typename std::allocator_traits<Alloc>::propagate_on_container_move_assignment());
293 size_t max_size() const noexcept {
return Alloc::max_size(); }
326 size_t oldSize =
size();
335 if (oldSize < n) std::uninitialized_fill<Tp*>(
_begin + oldSize,
_end, val);
359 const size_t curSize =
size();
364 _end = newStorage + curSize;
379 const size_t curSize =
size();
390 _end = newStorage + curSize;
405 Tp&
at(
size_t index) {
414 const Tp&
at(
size_t index)
const {
429 const Tp&
back() const noexcept {
return *(
_end - 1); }
443 template <
class InputIterator>
461 std::uninitialized_fill_n<Tp*, size_t>(
_begin, n, val);
469 void assign(std::initializer_list<Tp> initlist) {
478 for (
typename std::initializer_list<Tp>::const_iterator i = initlist.begin();
479 i != initlist.end(); ++i) {
505 *
_end = std::move(item);
522 size_t index = position -
_begin;
524 position =
_begin + index;
529 *
const_cast<iterator>(position) = item;
530 return const_cast<iterator>(position);
545 size_t index = position -
_begin;
547 position =
_begin + index;
552 std::uninitialized_fill_n<Tp*, size_t>(
const_cast<iterator>(position), n, val);
553 return const_cast<iterator>(position);
566 template <
class InputIterator>
569 std::is_integral<InputIterator>());
587 size_t index = position -
_begin;
589 position =
_begin + index;
594 *
const_cast<iterator>(position) = std::move(item);
595 return const_cast<iterator>(position);
609 size_t index = position -
_begin;
611 position =
_begin + index;
613 std::move_backward(
const_cast<iterator>(position),
_end,
_end + initlist.size());
614 _end += initlist.size();
617 for (
typename std::initializer_list<Tp>::const_iterator i = initlist.begin();
618 i != initlist.end(); ++i) {
622 return const_cast<iterator>(position);
634 return const_cast<iterator>(position);
662 swap(other,
typename std::allocator_traits<Alloc>::propagate_on_container_swap());
676 template <
typename... Args>
679 size_t index = position -
_begin;
681 position =
_begin + index;
686 *
const_cast<iterator>(position) = Tp(std::forward<Args>(args)...);
687 return const_cast<iterator>(position);
695 template <
typename... Args>
698 *
_end = Tp(std::forward<Args>(args)...);
722 size_t index = position -
_begin;
724 position =
_begin + index;
729 return const_cast<iterator>(position);
739 template <
class InputIterator>
755 std::uninitialized_fill_n<Tp*, size_t>(
_end, n, val);
769 for (
typename std::initializer_list<Tp>::iterator i = initlist.begin(); i != initlist.end();
790 if (
begin !=
nullptr) Alloc::deallocate(
begin, n);
793 template <
typename InputIterator>
796 first, last,
typename std::iterator_traits<InputIterator>::iterator_category());
799 template <
typename Integral>
804 std::uninitialized_fill_n<Tp*, size_t>(
_begin, n, val);
807 template <
typename InputIterator>
809 size_t n = std::distance(
first, last);
814 while (
first != last) {
821 template <
typename InputIterator>
824 first, last,
typename std::iterator_traits<InputIterator>::iterator_category());
830 template <
typename Integral>
839 std::uninitialized_fill_n<Tp*, size_t>(
_begin, n, val);
842 template <
typename InputIterator>
844 size_t n = std::distance(
first, last);
853 while (
first != last) {
860 template <
typename InputIterator>
864 position,
first, last,
typename std::iterator_traits<InputIterator>::iterator_category());
867 template <
typename Integral>
870 size_t index = position -
_begin;
872 position =
_begin + index;
877 std::uninitialized_fill_n<Tp*, size_t>(
const_cast<iterator>(position), n, val);
878 return const_cast<iterator>(position);
881 template <
typename InputIterator>
883 std::forward_iterator_tag) {
884 size_t n = std::distance(
first, last);
886 size_t index = position -
_begin;
888 position =
_begin + index;
893 Tp* destIter =
const_cast<iterator>(position);
894 while (
first != last) {
899 return const_cast<iterator>(position);
903 if (index >=
size())
throw std::out_of_range(
"Access to element in UVector past end");
907 return size() + std::max(
size(), extra_space_needed);
921 std::copy(
_begin,
_begin + insert_position, newStorage);
922 std::copy(
_begin + insert_position,
_end, newStorage + insert_position + insert_count);
924 _end = newStorage +
size() + insert_count;
932 const size_t n = other.
size();
950 const size_t n = other.
size();
957 Alloc::operator=(
static_cast<Alloc&
>(other));
965 std::false_type)
noexcept(allocator_is_always_equal::value) {
966 if (allocator_is_always_equal::value ||
967 static_cast<Alloc&
>(other) ==
static_cast<Alloc&
>(*
this)) {
972 other._begin =
nullptr;
973 other._end =
nullptr;
974 other._endOfStorage =
nullptr;
988 Alloc::operator=(std::move(
static_cast<Alloc&
>(other)));
992 other._begin =
nullptr;
993 other._end =
nullptr;
994 other._endOfStorage =
nullptr;
1000 std::swap(
_begin, other._begin);
1001 std::swap(
_end, other._end);
1003 std::swap(
static_cast<Alloc&
>(other),
static_cast<Alloc&
>(*
this));
1008 std::swap(
_begin, other._begin);
1009 std::swap(
_end, other._end);
1036 template <
typename InputIterator>
1039 first, last,
typename std::iterator_traits<InputIterator>::iterator_category());
1045 template <
typename Integral>
1050 std::uninitialized_fill_n<Tp*, size_t>(
_end, n, val);
1054 template <
typename InputIterator>
1056 size_t n = std::distance(
first, last);
1060 while (
first != last) {
1069template <
class Tp,
class Alloc>
1071 return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin());
1075template <
class Tp,
class Alloc>
1077 return !(lhs == rhs);
1084template <
class Tp,
class Alloc>
1086 const size_t minSize = std::min(lhs.size(), rhs.size());
1087 for (
size_t i = 0; i != minSize; ++i) {
1088 if (lhs[i] < rhs[i])
1090 else if (lhs[i] > rhs[i])
1093 return lhs.size() < rhs.size();
1100template <
class Tp,
class Alloc>
1102 const size_t minSize = std::min(lhs.size(), rhs.size());
1103 for (
size_t i = 0; i != minSize; ++i) {
1104 if (lhs[i] < rhs[i])
1106 else if (lhs[i] > rhs[i])
1109 return lhs.size() <= rhs.size();
1116template <
class Tp,
class Alloc>
1125template <
class Tp,
class Alloc>
1140template <
class Tp,
class Alloc>
A container similar to std::vector, but one that allows construction without initializing its element...
UVector & assign_copy_from(const UVector< Tp, Alloc > &other, std::false_type)
implementation of operator=(const&) without propagate_on_container_copy_assignment
iterator insert_from_range(const_iterator position, InputIterator first, InputIterator last, std::forward_iterator_tag)
void push_back_range(InputIterator first, InputIterator last, std::false_type)
size_t size() const noexcept
Get number of elements in container.
UVector & assign_move_from(UVector< Tp, Alloc > &&other, std::false_type) noexcept(allocator_is_always_equal::value)
implementation of operator=() without propagate_on_container_move_assignment
void push_back(Tp &&item)
Add the given value to the end of the container by moving it in.
void push_back_range(InputIterator first, InputIterator last, std::forward_iterator_tag)
void swap(UVector< Tp, Alloc > &other, std::true_type) noexcept
implementation of swap with propagate_on_container_swap
const Tp * data() const noexcept
Get constant pointer to internal storage.
UVector(UVector< Tp, Alloc > &&other) noexcept
Move construct a UVector.
void deallocate(pointer begin, size_t n) noexcept
UVector(const UVector< Tp, Alloc > &other, const allocator_type &allocator)
Copy construct a UVector with custom allocator.
Tp & emplace_back(Args &&... args)
Add the given value to the end of the container by constructing it in place.
void clear()
Remove all elements from the container.
UVector & assign_copy_from(const UVector< Tp, Alloc > &other, std::true_type)
implementation of operator=(const&) with propagate_on_container_copy_assignment
UVector & operator=(const UVector< Tp, Alloc > &other)
Assign another UVector to this UVector.
iterator insert(const_iterator position, size_t n, const Tp &val)
Insert elements at a given position and initialize them with a value.
void reserve(size_t n)
Reserve space for a number of elements, to prevent the overhead of extra reallocations.
iterator erase(const_iterator first, const_iterator last)
Delete a range of elements from the container.
const Tp & at(size_t index) const
Get a constant reference to the element at the given index with bounds checking.
void push_back(size_t n, const Tp &val)
Add elements at the end and initialize them with a value.
iterator insert(const_iterator position, const Tp &item)
Insert an element at a given position.
void assign_from_range(InputIterator first, InputIterator last, std::forward_iterator_tag)
size_t capacity() const noexcept
Get the number of elements the container can currently hold without reallocating storage.
Tp * data() noexcept
Get pointer to internal storage.
pointer allocate(size_t n)
void enlarge_for_insert(size_t newSize, size_t insert_position, size_t insert_count)
void assign(InputIterator first, InputIterator last)
Assign this container to be equal to the given range.
const_reverse_iterator crend() const noexcept
Get constant reverse iterator to element before first element.
void swap(UVector< Tp, Alloc > &other, std::false_type) noexcept
implementation of swap without propagate_on_container_swap
void shrink_to_fit()
Change the capacity of the container such that no extra space is hold.
std::ptrdiff_t difference_type
Difference between to iterators.
iterator emplace(const_iterator position, Args &&... args)
Insert an element at a given position by constructing it in place.
const Tp & operator[](size_t index) const noexcept
Get a constant reference to the element at the given index.
const Tp & back() const noexcept
Get constant reference to last element in container.
iterator insert_from_range(const_iterator position, Integral n, Integral val, std::true_type)
void push_back(const Tp &item)
Add the given value to the end of the container.
UVector(std::initializer_list< Tp > initlist, const allocator_type &allocator=Alloc())
Construct a UVector from a initializer list.
UVector(const allocator_type &allocator=Alloc()) noexcept
Construct an empty UVector.
void swap(UVector< Tp, Alloc > &other) noexcept
Swap the contents of this UVector with the given UVector.
void resize(size_t n, const Tp &val)
Change the number of elements in the container.
iterator erase(const_iterator position)
Delete an element from the container.
std::reverse_iterator< iterator > reverse_iterator
Reverse iterator type.
void resize(size_t n)
Change the number of elements in the container.
const_iterator begin() const noexcept
Get constant iterator to first element.
const Tp * const_pointer
Pointer to constant element type.
size_t max_size() const noexcept
Get maximum number of elements that this container can hold.
std::false_type allocator_is_always_equal
UVector(size_t n, const value_type &val, const allocator_type &allocator=Alloc())
Construct a vector with given amount of elements and set these to a specific value.
void assign_from_range(InputIterator first, InputIterator last, std::false_type)
const_reverse_iterator rbegin() const noexcept
Get constant reverse iterator to last element.
void push_back(std::initializer_list< Tp > initlist)
Add elements from an initializer list to the end of the container.
UVector(UVector< Tp, Alloc > &&other, const allocator_type &allocator) noexcept
Move construct a UVector with custom allocator.
void push_back_uninitialized(size_t n)
Add elements at the end without initializing them.
UVector & operator=(UVector< Tp, Alloc > &&other) noexcept(std::allocator_traits< Alloc >::propagate_on_container_move_assignment::value||allocator_is_always_equal::value)
Assign another UVector to this UVector.
void assign(std::initializer_list< Tp > initlist)
Assign this container to an initializer list.
void assign_from_range(Integral n, Integral val, std::true_type)
This function is called from assign(iter,iter) when Tp is an integral.
void construct_from_range(InputIterator first, InputIterator last, std::false_type)
reverse_iterator rbegin() noexcept
Get reverse iterator to last element.
void enlarge(size_t newSize)
std::size_t size_t
Type used for indexing elements.
allocator_type get_allocator() const noexcept
Get a copy of the allocator.
iterator insert(const_iterator position, InputIterator first, InputIterator last)
Insert elements at a given position and initialize them from a range.
UVector(const UVector< Tp, Alloc > &other)
Copy construct a UVector.
const_iterator cbegin() const noexcept
Get constant iterator to first element.
Tp & operator[](size_t index) noexcept
Get a reference to the element at the given index.
UVector(size_t n)
Construct a vector with given amount of elements, without initializing these.
void push_back_range(Integral n, Integral val, std::true_type)
This function is called from push_back(iter,iter) when Tp is an integral.
const_iterator cend() const noexcept
Get constant iterator to element past last element.
Tp & front() noexcept
Get reference to first element in container.
iterator insert_uninitialized(const_iterator position, size_t n)
— NON STANDARD METHODS —
void deallocate() noexcept
void pop_back()
Remove the last element from the container.
const_reverse_iterator crbegin() const noexcept
Get constant reverse iterator to last element.
Tp * pointer
Pointer to element type.
size_t enlarge_size(size_t extra_space_needed) const noexcept
void construct_from_range(InputIterator first, InputIterator last, std::forward_iterator_tag)
std::reverse_iterator< const_iterator > const_reverse_iterator
Reverse iterator of constant elements.
const Tp * const_iterator
Iterator type of constant elements.
~UVector() noexcept
Destructor.
UVector(InputIterator first, InputIterator last, const allocator_type &allocator=Alloc())
Construct a vector by copying elements from a range.
reverse_iterator rend() noexcept
Get reverse iterator to element before first element.
iterator insert(const_iterator position, std::initializer_list< Tp > initlist)
Insert elements at a given position and initialize them from a initializer list.
std::size_t size_type
Type used for indexing elements.
Tp & at(size_t index)
Get a reference to the element at the given index with bounds checking.
void check_bounds(size_t index) const
Tp & back() noexcept
Get reference to last element in container.
iterator insert(const_iterator position, Tp &&item)
Insert an element at a given position by moving it in.
void assign(size_t n, const Tp &val)
Resize the container and assign the given value to all elements.
iterator insert_from_range(const_iterator position, InputIterator first, InputIterator last, std::false_type)
Tp * iterator
Iterator type.
Tp & reference
Reference to element type.
UVector & assign_move_from(UVector< Tp, Alloc > &&other, std::true_type) noexcept
implementation of operator=() with propagate_on_container_move_assignment
const Tp & front() const noexcept
Get constant reference to first element in container.
const_iterator end() const noexcept
Get constant iterator to element past last element.
void push_back(InputIterator first, InputIterator last)
Add a range of items to the end of the container.
iterator end() noexcept
Get iterator to element past last element.
const_reverse_iterator rend() const noexcept
Get constant reverse iterator to element before first element.
bool empty() const noexcept
Determine if the container is currently empty.
const Tp & const_reference
Constant reference to element type.
Tp value_type
Element type.
iterator begin() noexcept
Get iterator to first element.
Alloc allocator_type
Type of allocator used to allocate and deallocate space.
void construct_from_range(Integral n, Integral val, std::true_type)
bool operator!=(const UVector< Tp, Alloc > &lhs, const UVector< Tp, Alloc > &rhs) noexcept
Compare two UVectors for inequality.
void swap(UVector< Tp, Alloc > &x, UVector< Tp, Alloc > &y)
Swap the contents of the two UVectors.
bool operator>(const UVector< Tp, Alloc > &lhs, const UVector< Tp, Alloc > &rhs) noexcept
Compare two UVectors for larger than.
bool operator<=(const UVector< Tp, Alloc > &lhs, const UVector< Tp, Alloc > &rhs) noexcept
Compare two UVectors for smaller than or equal.
bool operator>=(const UVector< Tp, Alloc > &lhs, const UVector< Tp, Alloc > &rhs) noexcept
Compare two UVectors for larger than or equal.
bool operator==(const UVector< Tp, Alloc > &lhs, const UVector< Tp, Alloc > &rhs) noexcept
Compare two UVectors for equality.
bool operator<(const UVector< Tp, Alloc > &lhs, const UVector< Tp, Alloc > &rhs) noexcept
Compare two UVectors for smaller than.
Define real & complex conjugation for non-complex types and put comparisons into std namespace.