#pragma once #include #include #include #include #include #include "common/Vec2.h" constexpr size_t DynamicExtent = std::numeric_limits::max(); template struct extentStorage { constexpr extentStorage(size_t) {} constexpr size_t getExtent() const { return Extent; } constexpr void setExtent(size_t) {} }; template<> struct extentStorage { size_t extent; constexpr extentStorage(size_t extent): extent(extent) {} constexpr size_t getExtent() const { return extent; } constexpr void setExtent(size_t extent) { this->extent = extent; } }; template struct xExtent: extentStorage { using extentStorage::extentStorage; }; template struct yExtent: extentStorage { using extentStorage::extentStorage; }; template struct baseStorage { using type = T; }; template struct baseStorage { using type = std::reference_wrapper; }; template struct baseStorage { using type = std::reference_wrapper; }; // A class that contains some container T and lets you index into it as if it // were a 2D array of size Width x Height, in row-major order. template class PlaneAdapter: xExtent, yExtent { using value_type = std::remove_reference_t()[0])>; using iterator = decltype(std::begin(std::declval())); using const_iterator = decltype(std::begin(std::declval())); size_t getWidth() const { return xExtent::getExtent(); } size_t getHeight() const { return yExtent::getExtent(); } std::remove_reference_t &getBase() { return Base; } std::remove_reference_t const &getBase() const { return Base; } public: typename baseStorage::type Base; PlaneAdapter(): xExtent(0), yExtent(0), Base() {} template PlaneAdapter(Vec2 size, Args&&... args): xExtent(size.X), yExtent(size.Y), Base(getWidth() * getHeight(), std::forward(args)...) {} template PlaneAdapter(Vec2 size, std::in_place_t, Args&&... args): xExtent(size.X), yExtent(size.Y), Base(std::forward(args)...) {} Vec2 Size() const { return Vec2(getWidth(), getHeight()); } void SetSize(Vec2 size) { xExtent::setExtent(size.X); yExtent::setExtent(size.Y); } iterator RowIterator(Vec2 p) { return std::begin(getBase()) + (p.X + p.Y * getWidth()); } const_iterator RowIterator(Vec2 p) const { return std::begin(getBase()) + (p.X + p.Y * getWidth()); } value_type *data() { return std::data(getBase()); } value_type const *data() const { return std::data(getBase()); } value_type &operator[](Vec2 p) { return getBase()[p.X + p.Y * getWidth()]; } value_type const &operator[](Vec2 p) const { return getBase()[p.X + p.Y * getWidth()]; } };