#pragma once
|
|
#include <initializer_list>
|
|
#include <gp/buffer.hpp>
|
|
|
|
namespace gp{
|
|
template<typename T, std::size_t sz>
|
|
class array{
|
|
public:
|
|
T ary[sz];
|
|
using associated_iterator = pointer_iterator<T, 1>;
|
|
using associated_const_iterator = const_pointer_iterator<T, 1>;
|
|
using associated_riterator = pointer_iterator<T, -1>;
|
|
using associated_const_riterator = const_pointer_iterator<T, -1>;
|
|
|
|
array()
|
|
: ary()
|
|
{}
|
|
|
|
array(const array& oth)
|
|
{
|
|
auto it_l = begin();
|
|
auto it_o = oth.cbegin();
|
|
for(size_t i = 0; i < sz; ++i)
|
|
{
|
|
new(&*(it_l++)) T(*(it_o++));
|
|
}
|
|
}
|
|
|
|
template<typename ...U>
|
|
array(U&& ...values)
|
|
: ary{gp::move((T&&)values)...}
|
|
{}
|
|
|
|
array(array&& values)
|
|
{
|
|
gp::move_uninitialized(
|
|
values,
|
|
*this
|
|
);
|
|
}
|
|
|
|
template<>
|
|
array<T[sz]>(T (& oth)[sz]) {
|
|
gp::move_uninitialized<T>(
|
|
gp::nameless_range(oth, oth+sz),
|
|
gp::nameless_range(begin(), end())
|
|
);
|
|
}
|
|
|
|
template<>
|
|
array<T[sz]>(T (&& oth)[sz]) {
|
|
gp::move_uninitialized(
|
|
gp::nameless_range(oth, oth+sz),
|
|
gp::nameless_range(begin(), end())
|
|
);
|
|
}
|
|
|
|
array& operator=(array& oth)
|
|
{
|
|
for(size_t i = 0; i < sz; ++i)
|
|
{
|
|
ary[i]=oth[i];
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
array& operator=(array&& oth)
|
|
{
|
|
for(size_t i = 0; i < sz; ++i)
|
|
{
|
|
ary[i]=gp::move(oth[i]);
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
constexpr T& operator[] (size_t off)
|
|
{
|
|
if constexpr (gp_config::has_buffer_bounds)
|
|
{
|
|
gp_config::assertion(
|
|
off < sz,
|
|
"Array bounds infringed"
|
|
);
|
|
}
|
|
return ary[off];
|
|
}
|
|
|
|
constexpr const T& operator[] (size_t off) const
|
|
{
|
|
return ary[off];
|
|
}
|
|
|
|
constexpr size_t size() const
|
|
{
|
|
return sz;
|
|
}
|
|
|
|
constexpr pointer_iterator<T, 1> begin()
|
|
{
|
|
return associated_iterator(&ary[0]);
|
|
}
|
|
|
|
constexpr pointer_iterator<T, 1> end()
|
|
{
|
|
return associated_iterator(&ary[sz]);
|
|
}
|
|
|
|
constexpr const_pointer_iterator<T, 1> cbegin() const
|
|
{
|
|
return associated_const_iterator(&ary[0]);
|
|
}
|
|
|
|
constexpr const_pointer_iterator<T, 1> cend() const
|
|
{
|
|
return associated_const_iterator(&ary[sz]);
|
|
}
|
|
|
|
constexpr pointer_iterator<T, -1> rbegin()
|
|
{
|
|
return associated_riterator(&ary[sz-1]);
|
|
}
|
|
|
|
constexpr pointer_iterator<T, -1> rend()
|
|
{
|
|
return associated_riterator(ary-1);
|
|
}
|
|
|
|
constexpr const_pointer_iterator<T, -1> crbegin() const
|
|
{
|
|
return associated_const_riterator(&ary[sz-1]);
|
|
}
|
|
|
|
constexpr const_pointer_iterator<T, -1> crend() const
|
|
{
|
|
return associated_const_riterator(ary-1);
|
|
}
|
|
|
|
constexpr bool operator==(const array& oth) const
|
|
{
|
|
for(size_t idx = 0; idx<sz; idx++)
|
|
{
|
|
if(ary[idx] != oth.ary[idx])
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
constexpr bool operator!=(const array& oth) const
|
|
{
|
|
return !(*this == oth);
|
|
}
|
|
|
|
gp::buffer<T> as_buffer()
|
|
{
|
|
return gp::buffer<T>{(T*)ary, (T*)ary+sz};
|
|
}
|
|
};
|
|
}
|