2023-12-24 14:39:12 +01:00
//
// Created by Patrick Maschek on 19.12.2023.
//
# ifndef UDIFF_IMMARRAY_H_
# define UDIFF_IMMARRAY_H_
# 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 :
T _arr [ N ] = { } ;
static constexpr const size_type _len = N ;
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
constexpr explicit const_vector ( const value_type ( & array ) [ N ] ) noexcept ;
constexpr const_vector ( std : : initializer_list < value_type > values ) noexcept ;
template < std : : input_iterator InputIt >
constexpr const_vector ( InputIt first , InputIt last ) ;
constexpr const_vector ( const const_vector & other ) noexcept ;
constexpr const_vector ( const_vector & & other ) noexcept ;
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 ;
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 ;
2023-12-31 17:06:25 +01:00
[[nodiscard]] constexpr reference front ( ) noexcept { return _arr [ 0 ] ; }
[[nodiscard]] constexpr const_reference front ( ) const noexcept { return _arr [ 0 ] ; }
[[nodiscard]] constexpr reference back ( ) noexcept { return _arr [ _size ] ; }
[[nodiscard]] constexpr const_reference back ( ) const noexcept { return _arr [ _size ] ; }
[[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 ; } ;
[[nodiscard]] constexpr const_iterator cbegin ( ) const noexcept { return _arr ; } ;
[[nodiscard]] constexpr iterator end ( ) 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 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 crend ( ) const noexcept { return std : : reverse_iterator < const_iterator > ( _arr ) ; } ;
2023-12-24 14:39:12 +01:00
[[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 ] ; }
# ifdef UNIT_TEST
friend test_const_vector ;
# endif
} ;
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 ) > ;
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 )
{
std : : move ( std : : begin ( array ) , std : : end ( array ) , _arr ) ;
}
template < typename T , std : : size_t N >
constexpr const_vector < T , N > : : const_vector ( std : : initializer_list < value_type > values ) noexcept
: _size ( values . size ( ) )
{
std : : move ( values . begin ( ) , values . end ( ) , _arr ) ;
}
template < typename T , std : : size_t N >
template < std : : input_iterator InputIt >
constexpr const_vector < T , N > : : const_vector ( InputIt first , InputIt 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 " ) ;
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 " ) ;
std : : move ( other . begin ( ) , other . end ( ) , _arr ) ;
}
template < typename T , std : : size_t N >
constexpr const_vector < T , N > & const_vector < T , N > : : operator = ( const const_vector & other )
{
if ( this = = & other ) return * this ;
static_assert ( N = = other . _len , " Cannot assign const_vector to other with different size " ) ;
2023-12-30 23:20:04 +01:00
assign ( other . begin ( ) , other . end ( ) ) ;
2023-12-24 14:39:12 +01:00
return * this ;
}
template < typename T , std : : size_t N >
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 ( ) ;
std : : move ( other . begin ( ) , other . end ( ) , _arr ) ;
return * this ;
}
template < typename T , std : : size_t N >
constexpr const_vector < T , N > & const_vector < T , N > : : operator = ( const value_type ( & array ) [ N ] ) noexcept
{
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 ;
}
2023-12-30 23:20:04 +01:00
template < typename T , std : : size_t N >
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 ) {
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 : : copy ( first , last , _arr ) ;
}
template < typename T , std : : size_t N >
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 ;
std : : copy ( values . begin ( ) , values . end ( ) , _arr ) ;
}
template < typename T , std : : size_t N >
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 {
if ( pos > = _size ) throw std : : out_of_range ( " Pos " + std : : to_string ( pos ) + " is out of range " ) ;
return _arr [ pos ] ;
}
2023-12-24 14:39:12 +01:00
} ; // cc
# endif //UDIFF_IMMARRAY_H_