#ifndef VALUE_ARRAY_H #define VALUE_ARRAY_H //TODO: option for non-constructed version (type_traits pod?), option for small array optimization (if sz < N, store inline in union, see small_vector.h) #include #include #include #include #include #include #include #ifdef USE_BOOST_SERIALIZE # include # include #endif //TODO: use awesome type traits (and/or policy typelist argument) to provide these only when possible? #define VALUE_ARRAY_ADD 1 #define VALUE_ARRAY_MUL 1 #define VALUE_ARRAY_BITWISE 0 #define VALUE_ARRAY_OSTREAM 1 #if VALUE_ARRAY_OSTREAM # include #endif // valarray like in that size is fixed (so saves space compared to vector), but same interface as vector (less resize/push_back/insert, of course) template > class ValueArray : A // private inheritance so stateless allocator adds no size. { typedef ValueArray Self; public: #if VALUE_ARRAY_OSTREAM friend inline std::ostream & operator << (std::ostream &o,Self const& s) { o<<'['; for (unsigned i=0,e=s.size();i1?sizeof(T)/sizeof(T*):1; //space optimization: SV_MAX T will fit inside what would otherwise be a pointer to heap data. todo in the far future if bored. typedef T value_type; typedef T& reference; typedef T const& const_reference; typedef T* iterator; typedef T const* const_iterator; typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; typedef T* pointer; size_type size() const { return sz; } bool empty() const { return size() == 0; } iterator begin() { return array; } iterator end() { return array + size(); } const_iterator begin() const { return array; } const_iterator end() const { return array + size(); } reference operator[](size_type pos) { return array[pos]; } const_reference operator[](size_type pos) const { return array[pos]; } reference at(size_type pos) { return array[pos]; } const_reference at(size_type pos) const { return array[pos]; } reference front() { return array[0]; } reference back() { return array[sz-1]; } const_reference front() const { return array[0]; } const_reference back() const { return array[sz-1]; } ValueArray() : sz(0), array(NULL) {} explicit ValueArray(size_type s, const_reference t = T()) { init(s,t); } protected: inline void init(size_type s, const_reference t = T()) { sz=s; array=s ? A::allocate(s) : 0; for (size_type i = 0; i != sz; ++i) { A::construct(array + i,t); } } public: void resize(size_type s, const_reference t = T()) { clear(); init(s,t); } template ValueArray(I itr, I end) : sz(std::distance(itr,end)) , array(A::allocate(sz)) { copy_construct(itr,end,array); } ~ValueArray() { clear(); } #undef VALUE_ARRAY_OPEQ #define VALUE_ARRAY_OPEQ(op) template Self & operator op (ValueArray const& o) { assert(sz==o.sz); for (int i=0,e=sz;i<=e;++i) array[i] op o.array[i]; return *this; } #if VALUE_ARRAY_ADD VALUE_ARRAY_OPEQ(+=) VALUE_ARRAY_OPEQ(-=) #endif #if VALUE_ARRAY_MUL VALUE_ARRAY_OPEQ(*=) VALUE_ARRAY_OPEQ(/=) #endif #if VALUE_ARRAY_BITWISE VALUE_ARRAY_OPEQ(|=) VALUE_ARRAY_OPEQ(*=) #endif #undef VALUE_ARRAY_OPEQ #undef VALUE_ARRAY_BINOP #define VALUE_ARRAY_BINOP(op,opeq) template friend inline Self operator op (Self x,ValueArray const& y) { x opeq y; return x; } #if VALUE_ARRAY_ADD VALUE_ARRAY_BINOP(+,+=) VALUE_ARRAY_BINOP(-,-=) #endif #if VALUE_ARRAY_MUL VALUE_ARRAY_BINOP(*,*=) VALUE_ARRAY_BINOP(/,/=) #endif #if VALUE_ARRAY_BITWISE VALUE_ARRAY_BINOP(|,|=) VALUE_ARRAY_BINOP(*,*=) #endif #undef VALUE_ARRAY_BINOP void clear() { for (size_type i = sz; i != 0; --i) { A::destroy(array + (i - 1)); } if (array != NULL) A::deallocate(array,sz); } void swap(ValueArray& other) { std::swap(sz,other.sz); std::swap(array,other.array); } ValueArray(ValueArray const& other) : A(other) , sz(other.sz) , array(A::allocate(sz)) { copy_construct(other.begin(),other.end(),array); } ValueArray& operator=(ValueArray const& other) { ValueArray(other).swap(*this); return *this; } template ValueArray( Range const& v , typename boost::disable_if< boost::is_integral >::type* = 0) : sz(boost::size(v)) , array(A::allocate(sz)) { copy_construct(boost::begin(v),boost::end(v),array); } template typename boost::disable_if< boost::is_integral , ValueArray>::type& operator=(Range const& other) { ValueArray(other).swap(*this); return *this; } private: //friend class boost::serialization::access; template void copy_construct(I1 itr, I1 end, I2 into) { for (; itr != end; ++itr, ++into) A::construct(into,*itr); } template void save(Archive& ar, unsigned int version) const { ar << sz; for (size_type i = 0; i != sz; ++i) ar << at(i); } template void load(Archive& ar, unsigned int version) { size_type s; ar >> s; ValueArray v(s); for (size_type i = 0; i != s; ++i) ar >> v[i]; this->swap(v); } #ifdef USE_BOOST_SERIALIZE BOOST_SERIALIZATION_SPLIT_MEMBER() #endif size_type sz; pointer array; }; template bool operator==(ValueArray const& v1, ValueArray const& v2) { return (v1.size() == v2.size()) and std::equal(v1.begin(),v1.end(),v2.begin()); } template bool operator< (ValueArray const& v1, ValueArray const& v2) { return std::lexicographical_compare( v1.begin() , v1.end() , v2.begin() , v2.end() ); } template void memcpy(void *out,ValueArray const& v) { std::memcpy(out,v.begin(),v.size()*sizeof(T)); } #endif