// // nd_array.hpp // AwesomeAttractorND // // Created by Joshua Moerman on 10/25/11. // Copyright 2011 Vadovas. All rights reserved. // /* Dynamic multi-dimensional array. With the usual c-syntax: v[x][y][z]. Memory is allocated as one big block, instead of multiple smaller blocks (which is the case with std::vector>). Showed no difference in speed compared to std::array> (in release build). it is not yet standard compliant. */ #ifndef AwesomeAttractorND_nd_array_hpp #define AwesomeAttractorND_nd_array_hpp #include #include #include #include "array.hpp" template class nd_array{ public: typedef T & reference; typedef T const & const_reference; typedef T * iterator; typedef T const * const_iterator; typedef size_t size_type; typedef ptrdiff_t difference_type; typedef T value_type; typedef T * pointer; typedef T const * const_pointer; typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; template struct proxy { nd_array * const data; size_t const offset; proxy(nd_array * const c, size_t o) : data(c) , offset(o) {} proxy operator[](size_t y){ if (N == 0) throw std::logic_error("called operator[] on a value"); return proxy(data, data->sizes[dimension - N]*offset + y); } operator reference(){ if (N != 0) throw std::logic_error("using a non-value"); return *(data->data + offset); } reference operator=(T const & n){ if (N != 0) throw std::logic_error("assignment to a non-value"); return *(data->data + offset) = n; } }; template struct const_proxy { nd_array const * const data; size_t const offset; const_proxy(nd_array const * const c, size_t o) : data(c) , offset(o) {} const_proxy operator[](size_t y) const { if (N == 0) throw std::logic_error("called operator[] on a value"); return const_proxy(data, data->sizes[dimension - N]*offset + y); } operator const_reference() const { if (N != 0) throw std::logic_error("using a non-value"); return *(data->data + offset); } }; nd_array(size_type width, size_type height) : data(0) , sizes() { if (dimension != 2) throw std::logic_error("wrong constructor"); sizes[0] = width; sizes[1] = height; data = new T[width*height]; } nd_array(size_type width, size_type height, size_type depth) : data(0) , sizes() { if (dimension != 3) throw std::logic_error("wrong constructor"); sizes[0] = width; sizes[1] = height; sizes[2] = depth; data = new T[width*height*depth]; } ~nd_array(){ delete[] data; } size_type get_size(size_type d) const { return sizes[d]; } size_type size() const { return std::accumulate(sizes.begin(), sizes.end(), 1, std::multiplies()); } proxy operator[](size_t x){ return proxy(this, x); } const_proxy operator[](size_t x) const { return const_proxy(this, x); } iterator begin(){ return data; } iterator end(){ size_type length = size(); return data + length; } const_iterator cbegin() const { return data; } const_iterator cend() const { size_type length = size(); return data + length; } private: T * data; std::array sizes; }; #endif