2023-12-24 14:39:12 +01:00
//
// Created by Patrick Maschek on 19.12.2023.
//
2024-01-06 18:27:30 +01:00
# ifndef CONST_CONTAINER_CONST_VEC_H_
# define CONST_CONTAINER_CONST_VEC_H_
2023-12-24 14:39:12 +01:00
# include <algorithm>
# include <initializer_list>
# include <iterator>
# include <utility>
# include "helper.h"
namespace cc {
template < typename T , std : : size_t N >
class const_vector {
static_assert ( N > 0 , " Capacity of const_vector has to be greater than 0 " ) ;
public :
using value_type = T ;
using size_type = std : : size_t ;
using difference_type = std : : 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 ;
using reverse_iterator = std : : reverse_iterator < iterator > ;
using const_reverse_iterator = std : : reverse_iterator < const_iterator > ;
protected :
static constexpr const size_type _len = N ;
2024-01-06 18:11:11 +01:00
T _arr [ N ] = { } ;
2023-12-24 14:39:12 +01:00
size_type _size = 0 ;
public :
constexpr const_vector ( ) noexcept = default ;
2023-12-30 23:20:04 +01:00
constexpr explicit const_vector ( const value_type & value ) noexcept ;
constexpr const_vector ( size_type count , const value_type & value ) noexcept ;
2023-12-24 14:39:12 +01:00
2024-07-28 23:34:22 +02:00
constexpr const_vector ( const value_type ( & array ) [ N ] ) noexcept ;
2024-07-21 22:28:35 +02:00
template < std : : size_t N2 >
2024-07-27 21:44:05 +02:00
constexpr explicit const_vector ( const value_type ( & array ) [ N2 ] ) ;
2023-12-24 14:39:12 +01:00
2024-07-22 23:30:24 +02:00
constexpr const_vector ( std : : initializer_list < value_type > values ) ;
2023-12-24 14:39:12 +01:00
template < std : : input_iterator InputIt >
constexpr const_vector ( InputIt first , InputIt last ) ;
2024-01-06 18:11:11 +01:00
constexpr const_vector ( const const_vector < value_type , N > & other ) noexcept ;
template < std : : size_t N2 >
constexpr const_vector ( const const_vector < value_type , N2 > & other ) ;
2023-12-24 14:39:12 +01:00
constexpr const_vector ( const_vector & & other ) noexcept ;
2024-07-22 22:51:22 +02:00
template < std : : size_t N2 >
constexpr const_vector ( const_vector < value_type , N2 > & & other ) ;
2023-12-24 14:39:12 +01:00
2024-01-04 16:16:44 +01:00
constexpr ~ const_vector ( ) = default ; // elements in static array should be destroyed automatically
2024-07-22 23:30:24 +02:00
constexpr const_vector < T , N > & operator = ( const const_vector & other ) noexcept ; // needed to handle *this = *this
2024-01-06 23:37:44 +01:00
template < std : : size_t N2 >
constexpr const_vector < T , N > & operator = ( const const_vector < value_type , N2 > & other ) ;
2023-12-24 14:39:12 +01:00
constexpr const_vector < T , N > & operator = ( const_vector & & other ) noexcept ;
2024-07-22 22:51:22 +02:00
template < std : : size_t N2 >
constexpr const_vector < T , N > & operator = ( const_vector < value_type , N2 > & & other ) ;
2024-07-28 16:47:05 +02:00
//constexpr const_vector<T, N>& operator=(const value_type (&array)[N]) noexcept; // not needed as functionally equivalent to templated overload, could be noexcept though
2024-01-06 23:37:44 +01:00
template < std : : size_t N2 >
2024-07-22 23:30:24 +02:00
constexpr const_vector < T , N > & operator = ( const value_type ( & array ) [ N2 ] ) ;
constexpr const_vector < T , N > & operator = ( std : : initializer_list < value_type > values ) ;
2023-12-24 14:39:12 +01:00
2023-12-30 23:20:04 +01:00
constexpr void assign ( size_type count , const value_type & value ) noexcept ;
template < std : : input_iterator InputIt >
constexpr void assign ( InputIt first , InputIt last ) ;
constexpr void assign ( std : : initializer_list < value_type > values ) ;
constexpr reference at ( size_type pos ) ;
constexpr const_reference at ( size_type pos ) const ;
2024-01-04 16:16:44 +01:00
constexpr T & operator [ ] ( size_type pos ) { return _arr [ pos ] ; }
constexpr const T & operator [ ] ( size_type pos ) const { return _arr [ pos ] ; }
2024-07-29 00:38:52 +02:00
[[nodiscard]] constexpr reference front ( ) noexcept { return _arr [ 0 ] ; }
2023-12-31 17:06:25 +01:00
[[nodiscard]] constexpr const_reference front ( ) const noexcept { return _arr [ 0 ] ; }
2024-07-29 00:38:52 +02:00
[[nodiscard]] constexpr reference back ( ) noexcept { return _arr [ _size - 1 ] ; }
[[nodiscard]] constexpr const_reference back ( ) const noexcept { return _arr [ _size - 1 ] ; }
2023-12-31 17:06:25 +01:00
[[nodiscard]] constexpr value_type * data ( ) noexcept { return _arr ; }
[[nodiscard]] constexpr const value_type * data ( ) const noexcept { return _arr ; }
[[nodiscard]] constexpr iterator begin ( ) noexcept { return _arr ; } ;
2024-01-04 16:16:44 +01:00
[[nodiscard]] constexpr const_iterator begin ( ) const noexcept { return _arr ; } ;
2023-12-31 17:06:25 +01:00
[[nodiscard]] constexpr const_iterator cbegin ( ) const noexcept { return _arr ; } ;
[[nodiscard]] constexpr iterator end ( ) noexcept { return _arr + _size ; } ;
2024-01-04 16:16:44 +01:00
[[nodiscard]] constexpr const_iterator end ( ) const noexcept { return _arr + _size ; } ;
2023-12-31 17:06:25 +01:00
[[nodiscard]] constexpr const_iterator cend ( ) const noexcept { return _arr + _size ; } ;
[[nodiscard]] constexpr reverse_iterator rbegin ( ) noexcept { return std : : reverse_iterator < iterator > ( _arr + _size ) ; } ;
2024-01-04 16:16:44 +01:00
[[nodiscard]] constexpr const_reverse_iterator rbegin ( ) const noexcept { return std : : reverse_iterator < const_iterator > ( _arr + _size ) ; } ;
2023-12-31 17:06:25 +01:00
[[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 ) ; } ;
2024-01-04 16:16:44 +01:00
[[nodiscard]] constexpr const_reverse_iterator rend ( ) const noexcept { return std : : reverse_iterator < const_iterator > ( _arr ) ; } ;
2023-12-31 17:06:25 +01:00
[[nodiscard]] constexpr const_reverse_iterator crend ( ) const noexcept { return std : : reverse_iterator < const_iterator > ( _arr ) ; } ;
2024-01-04 16:16:44 +01:00
[[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 ; }
2023-12-24 14:39:12 +01:00
[[nodiscard]] constexpr size_type size ( ) const noexcept { return _size ; }
2024-07-29 16:31:03 +02:00
constexpr void clear ( ) ;
2024-01-04 16:16:44 +01:00
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 ) ;
2024-07-22 22:51:22 +02:00
template < typename T2 , std : : size_t N2 >
friend class const_vector ;
2023-12-24 14:39:12 +01:00
} ;
template < typename A >
const_vector ( A [ ] ) - > const_vector < A , helper : : array_size < A > > ;
template < typename . . . T >
const_vector ( T . . . ) - > const_vector < std : : common_type_t < T . . . > , sizeof . . . ( T ) > ;
2024-01-04 16:16:44 +01:00
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 ;
}
2023-12-24 14:39:12 +01:00
template < typename T , std : : size_t N >
2023-12-30 23:20:04 +01:00
constexpr const_vector < T , N > : : const_vector ( const value_type & value ) noexcept
2023-12-24 14:39:12 +01:00
: _size ( N )
{
std : : fill ( std : : begin ( _arr ) , std : : end ( _arr ) , value ) ;
}
template < typename T , std : : size_t N >
2023-12-30 23:20:04 +01:00
constexpr const_vector < T , N > : : const_vector ( size_type count , const value_type & value ) noexcept
2023-12-24 14:39:12 +01:00
{
2023-12-30 23:20:04 +01:00
if ( count > N ) count = N ;
_size = count ;
2023-12-24 14:39:12 +01:00
std : : fill ( _arr , _arr + _size , value ) ;
}
template < typename T , std : : size_t N >
constexpr const_vector < T , N > : : const_vector ( const value_type ( & array ) [ N ] ) noexcept
: _size ( N )
{
2024-07-27 21:44:05 +02:00
std : : copy ( std : : begin ( array ) , std : : end ( array ) , _arr ) ;
}
template < typename T , std : : size_t N >
template < std : : size_t N2 >
constexpr const_vector < T , N > : : const_vector ( const value_type ( & array ) [ N2 ] )
: _size ( N2 )
{
if ( N < N2 ) throw std : : invalid_argument ( " Size of array has to be smaller or equal to the capacity: " + std : : to_string ( N2 ) + " >= " + std : : to_string ( N ) ) ;
std : : copy ( std : : begin ( array ) , std : : end ( array ) , _arr ) ;
2023-12-24 14:39:12 +01:00
}
template < typename T , std : : size_t N >
2024-07-22 23:30:24 +02:00
constexpr const_vector < T , N > : : const_vector ( std : : initializer_list < value_type > values )
2023-12-24 14:39:12 +01:00
: _size ( values . size ( ) )
{
2024-07-22 23:30:24 +02:00
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 ) ) ;
2023-12-24 14:39:12 +01:00
std : : move ( values . begin ( ) , values . end ( ) , _arr ) ;
}
template < typename T , std : : size_t N >
template < std : : input_iterator InputIt >
2024-01-04 16:16:44 +01:00
constexpr const_vector < T , N > : : const_vector ( InputIt first , InputIt last )
2024-01-06 18:11:11 +01:00
: _size ( std : : distance ( first , last ) )
{
if ( std : : distance ( first , last ) > N ) throw std : : invalid_argument ( " tried inserting more elements than const_vector is in size " ) ;
2023-12-24 14:39:12 +01:00
std : : copy ( first , last , _arr ) ;
2024-01-06 18:11:11 +01:00
}
template < typename T , std : : size_t N >
constexpr const_vector < T , N > : : const_vector ( const const_vector & other ) noexcept
: _size ( other . _size )
{
std : : copy ( other . begin ( ) , other . end ( ) , _arr ) ;
_size = other . _size ;
}
2023-12-24 14:39:12 +01:00
template < typename T , std : : size_t N >
2024-01-06 18:11:11 +01:00
template < std : : size_t N2 >
constexpr const_vector < T , N > : : const_vector ( const const_vector < const_vector : : value_type , N2 > & other )
: _size ( other . size ( ) )
2024-01-04 16:16:44 +01:00
{
2024-01-06 18:11:11 +01:00
if ( _len < = other . size ( ) ) throw std : : invalid_argument ( " size of other has to be equal to or smaller than this " ) ;
std : : copy ( other . begin ( ) , other . end ( ) , _arr ) ;
}
2023-12-24 14:39:12 +01:00
template < typename T , std : : size_t N >
2024-01-04 16:16:44 +01:00
constexpr const_vector < T , N > : : const_vector ( const_vector & & other ) noexcept
: _size ( other . _size )
{
2023-12-24 14:39:12 +01:00
std : : move ( other . begin ( ) , other . end ( ) , _arr ) ;
}
2024-07-22 22:51:22 +02:00
template < typename T , std : : size_t N >
template < std : : size_t N2 >
constexpr const_vector < T , N > : : const_vector ( const_vector < value_type , N2 > & & other )
: _size ( other . _size )
{
if ( _len < = other . size ( ) ) throw std : : invalid_argument ( " size of other has to be equal to or smaller than this " ) ;
std : : move ( other . begin ( ) , other . end ( ) , _arr ) ;
}
2023-12-24 14:39:12 +01:00
template < typename T , std : : size_t N >
2024-07-22 23:30:24 +02:00
constexpr const_vector < T , N > & const_vector < T , N > : : operator = ( const const_vector & other ) noexcept
2023-12-24 14:39:12 +01:00
{
if ( this = = & other ) return * this ;
2023-12-30 23:20:04 +01:00
2024-07-22 23:30:24 +02:00
// event though assign may throw an exception noexcept for this operator should be fine,
// as std::distance(other.begin(), other.end()) cannot be greater than the capacity,
// because the signatures would have to differ
2023-12-30 23:20:04 +01:00
assign ( other . begin ( ) , other . end ( ) ) ;
2023-12-24 14:39:12 +01:00
return * this ;
}
2024-01-06 23:37:44 +01:00
template < typename T , std : : size_t N >
template < std : : size_t N2 >
constexpr const_vector < T , N > & const_vector < T , N > : : operator = ( const const_vector < const_vector : : value_type , N2 > & other )
{
if ( other . size ( ) > _len ) throw std : : invalid_argument ( " size of other has to be equal to or smaller than this " ) ;
// this is not necessary, as it should call the non templated operator=
2024-07-22 23:30:24 +02:00
// (and throws an error without a cast)
2024-01-06 23:37:44 +01:00
//if (this == &other) return *this;
assign ( other . begin ( ) , other . end ( ) ) ;
return * this ;
}
2023-12-24 14:39:12 +01:00
template < typename T , std : : size_t N >
constexpr const_vector < T , N > & const_vector < T , N > : : operator = ( const_vector & & other ) noexcept
{
2024-01-06 23:37:44 +01:00
// cannot occur, otherwise signature would differ
//static_assert(N == other._len, "Cannot assign const_vector to other with different size");
//if (N != other._len) throw std::exception();
2024-01-04 16:16:44 +01:00
clear ( ) ;
2023-12-24 14:39:12 +01:00
std : : move ( other . begin ( ) , other . end ( ) , _arr ) ;
2024-01-04 16:16:44 +01:00
_size = other . _size ;
2023-12-24 14:39:12 +01:00
return * this ;
}
2024-07-22 22:51:22 +02:00
template < typename T , std : : size_t N >
template < std : : size_t N2 >
constexpr const_vector < T , N > & const_vector < T , N > : : operator = ( const_vector < value_type , N2 > & & other )
{
if ( other . size ( ) > _len ) throw std : : invalid_argument ( " size of other has to be equal to or smaller than this " ) ;
clear ( ) ;
std : : move ( other . begin ( ) , other . end ( ) , _arr ) ;
_size = other . _size ;
return * this ;
}
2023-12-24 14:39:12 +01:00
template < typename T , std : : size_t N >
2024-01-06 23:37:44 +01:00
template < std : : size_t N2 >
2024-07-22 23:30:24 +02:00
constexpr const_vector < T , N > & const_vector < T , N > : : operator = ( const value_type ( & array ) [ N2 ] )
2023-12-24 14:39:12 +01:00
{
2023-12-30 23:20:04 +01:00
assign ( std : : begin ( array ) , std : : end ( array ) ) ;
2023-12-24 14:39:12 +01:00
return * this ;
}
2024-01-07 21:42:26 +01:00
template < typename T , std : : size_t N >
2024-07-22 23:30:24 +02:00
constexpr const_vector < T , N > & const_vector < T , N > : : operator = ( std : : initializer_list < value_type > values )
2024-01-07 21:42:26 +01:00
{
assign ( std : : move ( values ) ) ;
return * this ;
}
2023-12-30 23:20:04 +01:00
template < typename T , std : : size_t N >
2024-01-04 16:16:44 +01:00
constexpr void const_vector < T , N > : : assign ( const_vector : : size_type count , const value_type & value ) noexcept
{
2023-12-30 23:20:04 +01:00
if ( count > N ) count = N ;
_size = count ;
2024-01-04 16:16:44 +01:00
2023-12-30 23:20:04 +01:00
std : : fill ( std : : begin ( _arr ) , std : : end ( _arr ) , value ) ;
}
template < typename T , std : : size_t N >
template < std : : input_iterator InputIt >
2024-01-04 16:16:44 +01:00
constexpr void const_vector < T , N > : : assign ( InputIt first , InputIt last )
{
2023-12-30 23:20:04 +01:00
auto distance = std : : distance ( first , last ) ;
2024-07-22 23:30:24 +02:00
if ( distance > N ) throw std : : invalid_argument ( " Iterator distance in assign surpasses size " + std : : to_string ( distance ) + " >= " + std : : to_string ( N ) ) ;
2023-12-30 23:20:04 +01:00
_size = distance ;
2024-01-15 11:51:23 +01:00
std : : copy ( first , last , begin ( ) ) ;
2023-12-30 23:20:04 +01:00
}
template < typename T , std : : size_t N >
2024-01-04 16:16:44 +01:00
constexpr void const_vector < T , N > : : assign ( std : : initializer_list < value_type > values )
{
2024-07-24 18:44:26 +02:00
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 ) ) ;
2024-07-24 17:57:20 +02:00
_size = values . size ( ) ;
2023-12-30 23:20:04 +01:00
std : : copy ( values . begin ( ) , values . end ( ) , _arr ) ;
}
template < typename T , std : : size_t N >
2024-01-04 16:16:44 +01:00
constexpr const_vector < T , N > : : reference const_vector < T , N > : : at ( const_vector : : size_type pos )
{
2023-12-30 23:20:04 +01:00
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 >
2024-01-04 16:16:44 +01:00
constexpr const_vector < T , N > : : const_reference const_vector < T , N > : : at ( const_vector : : size_type pos ) const
{
2023-12-30 23:20:04 +01:00
if ( pos > = _size ) throw std : : out_of_range ( " Pos " + std : : to_string ( pos ) + " is out of range " ) ;
return _arr [ pos ] ;
}
2024-07-29 16:31:03 +02:00
template < typename T , std : : size_t N >
constexpr void const_vector < T , N > : : clear ( )
{
std : : destroy ( begin ( ) , end ( ) ) ;
_size = 0 ;
}
2024-01-04 16:16:44 +01:00
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 )
{
2024-07-29 16:31:32 +02:00
if ( _size = = N ) throw std : : length_error ( " No space left in vector " ) ;
2024-01-04 16:16:44 +01:00
2024-07-29 16:31:32 +02:00
auto it = const_cast < iterator > ( pos ) ;
2024-01-04 16:16:44 +01:00
2024-07-29 16:31:32 +02:00
if ( pos ! = end ( ) ) {
std : : move_backward ( it , end ( ) , end ( ) + 1 ) ;
}
* it = value ;
2024-01-04 16:16:44 +01:00
+ + _size ;
2024-07-29 16:31:32 +02:00
return it ;
2024-01-04 16:16:44 +01:00
}
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 )
{
2024-07-29 16:31:32 +02:00
if ( _size = = N ) throw std : : length_error ( " No space left in vector " ) ;
2024-01-04 16:16:44 +01:00
2024-07-29 16:31:32 +02:00
auto it = const_cast < iterator > ( pos ) ;
2024-01-04 16:16:44 +01:00
2024-07-29 16:31:32 +02:00
if ( pos ! = end ( ) ) {
std : : move_backward ( it , end ( ) , end ( ) + 1 ) ;
}
* it = std : : forward < value_type > ( value ) ;
2024-01-04 16:16:44 +01:00
+ + _size ;
2024-07-29 16:31:32 +02:00
return it ;
2024-01-04 16:16:44 +01:00
}
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 )
{
2024-07-29 16:31:32 +02:00
auto it = const_cast < iterator > ( pos ) ;
if ( count = = 0 ) return it ;
if ( _size + count > N ) throw std : : length_error ( " Not enough space left in vector for " + std : : to_string ( count ) + " elements " ) ;
2024-01-04 16:16:44 +01:00
2024-07-29 16:31:32 +02:00
std : : move_backward ( it , end ( ) , end ( ) + count ) ;
std : : fill ( it , it + count , value ) ;
2024-01-04 16:16:44 +01:00
_size + = count ;
2024-07-29 16:31:32 +02:00
return it ;
2024-01-04 16:16:44 +01:00
}
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 ) ;
2024-07-29 16:31:32 +02:00
auto it = const_cast < iterator > ( pos ) ;
2024-01-04 16:16:44 +01:00
2024-07-29 16:31:32 +02:00
if ( first = = last ) return it ;
if ( _size + count > N ) throw std : : length_error ( " Not enough space left in vector for " + std : : to_string ( count ) + " elements " ) ;
2024-01-04 16:16:44 +01:00
2024-07-29 16:31:32 +02:00
std : : move_backward ( it , end ( ) , end ( ) + count ) ;
std : : copy ( first , last , it ) ;
2024-01-04 16:16:44 +01:00
_size + = count ;
2024-07-29 16:31:32 +02:00
return it ;
2024-01-04 16:16:44 +01:00
}
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 >
2024-07-29 16:53:38 +02:00
template < typename . . . Args >
2024-01-04 16:16:44 +01:00
constexpr const_vector < T , N > : : iterator const_vector < T , N > : : emplace ( const_vector : : const_iterator pos , Args & & . . . args )
{
2024-07-29 16:53:38 +02:00
if ( _size = = N ) throw std : : length_error ( " No space left in vector " ) ;
2024-01-04 16:16:44 +01:00
2024-07-29 16:53:38 +02:00
auto it = const_cast < iterator > ( pos ) ;
if ( it ! = end ( ) ) {
std : : move_backward ( it , end ( ) , end ( ) + 1 ) ;
}
* it = T ( std : : forward < Args > ( args ) . . . ) ;
+ + _size ;
return it ;
2024-01-04 16:16:44 +01:00
}
template < typename T , std : : size_t N >
constexpr const_vector < T , N > : : iterator const_vector < T , N > : : erase ( const_vector : : const_iterator pos )
{
2024-07-29 17:22:47 +02:00
auto it = const_cast < iterator > ( pos ) ;
std : : destroy_n ( it , 1 ) ;
std : : move ( it + 1 , end ( ) , it ) ;
2024-01-04 16:16:44 +01:00
- - _size ;
2024-07-29 17:22:47 +02:00
return it ;
2024-01-04 16:16:44 +01:00
}
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 )
{
2024-07-29 17:22:47 +02:00
auto _first = const_cast < iterator > ( first ) ;
auto _last = const_cast < iterator > ( last ) ;
if ( _first = = _last ) return _last ;
std : : destroy ( _first , _last ) ;
std : : move ( _last , end ( ) , _first ) ;
_size - = std : : distance ( _first , _last ) ;
2024-01-04 16:16:44 +01:00
2024-07-29 17:22:47 +02:00
return _first ;
2024-01-04 16:16:44 +01:00
}
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 ) ;
}
2023-12-24 14:39:12 +01:00
} ; // cc
2024-01-06 18:27:30 +01:00
# endif //CONST_CONTAINER_CONST_VEC_H_