#pragma once #include #include "StarHash.hpp" namespace Star { // Somewhat nicer form of std::array, always initializes values, uses nicer // constructor pattern. template class Array : public std::array { public: typedef std::array Base; typedef ElementT Element; static size_t const ArraySize = SizeN; typedef Element* iterator; typedef Element const* const_iterator; typedef Element& reference; typedef Element const& const_reference; typedef Element value_type; static Array filled(Element const& e); template static Array copyFrom(Iterator p, size_t n = NPos); Array(); explicit Array(Element const& e1); template Array(Element const& e1, T const&... rest); template explicit Array(Array const& a); template reference get(); template const_reference get() const; template Array& operator=(Array const& array); Element* ptr(); Element const* ptr() const; bool operator==(Array const& a) const; bool operator!=(Array const& a) const; bool operator<(Array const& a) const; bool operator<=(Array const& a) const; bool operator>(Array const& a) const; bool operator>=(Array const& a) const; template Array toSize() const; private: // Instead of {} array initialization, use recursive assignment to mimic old // C++ style construction with less strict narrowing rules. template void set(T const& e, TL const&... rest); void set(); }; template struct hash> { size_t operator()(Array const& a) const; Star::hash dataHasher; }; typedef Array Array2I; typedef Array Array2S; typedef Array Array2U; typedef Array Array2F; typedef Array Array2D; typedef Array Array3I; typedef Array Array3S; typedef Array Array3U; typedef Array Array3F; typedef Array Array3D; typedef Array Array4I; typedef Array Array4S; typedef Array Array4U; typedef Array Array4F; typedef Array Array4D; template Array Array::filled(Element const& e) { Array a; a.fill(e); return a; } template template Array Array::copyFrom(Iterator p, size_t n) { Array a; for (size_t i = 0; i < n && i < Size; ++i) a[i] = *(p++); return a; } template Array::Array() : Base() {} template Array::Array(Element const& e1) { static_assert(Size == 1, "Incorrect size in Array constructor"); set(e1); } template template Array::Array(Element const& e1, T const&... rest) { static_assert(sizeof...(rest) == Size - 1, "Incorrect size in Array constructor"); set(e1, rest...); } template template Array::Array(Array const& a) { std::copy(a.begin(), a.end(), Base::begin()); } template template auto Array::get() -> reference { static_assert(i < Size, "Incorrect size in Array::at"); return Base::operator[](i); } template template auto Array::get() const -> const_reference { static_assert(i < Size, "Incorrect size in Array::at"); return Base::operator[](i); } template template Array& Array::operator=(Array const& array) { std::copy(array.begin(), array.end(), Base::begin()); return *this; } template Element* Array::ptr() { return Base::data(); } template Element const* Array::ptr() const { return Base::data(); } template bool Array::operator==(Array const& a) const { for (size_t i = 0; i < Size; ++i) if ((*this)[i] != a[i]) return false; return true; } template bool Array::operator!=(Array const& a) const { return !operator==(a); } template bool Array::operator<(Array const& a) const { for (size_t i = 0; i < Size; ++i) { if ((*this)[i] < a[i]) return true; else if (a[i] < (*this)[i]) return false; } return false; } template bool Array::operator<=(Array const& a) const { for (size_t i = 0; i < Size; ++i) { if ((*this)[i] < a[i]) return true; else if (a[i] < (*this)[i]) return false; } return true; } template bool Array::operator>(Array const& a) const { return a < *this; } template bool Array::operator>=(Array const& a) const { return a <= *this; } template template Array Array::toSize() const { Array r; size_t ns = std::min(Size2, Size); for (size_t i = 0; i < ns; ++i) r[i] = (*this)[i]; return r; } template void Array::set() {} template template void Array::set(T const& e, TL const&... rest) { Base::operator[](Size - 1 - sizeof...(rest)) = e; set(rest...); } template std::ostream& operator<<(std::ostream& os, Array const& a) { os << '['; for (size_t i = 0; i < Size; ++i) { os << a[i]; if (i != Size - 1) os << ", "; } os << ']'; return os; } template size_t hash>::operator()(Array const& a) const { size_t hashval = 0; for (size_t i = 0; i < SizeT; ++i) hashCombine(hashval, dataHasher(a[i])); return hashval; } }