Double-Bound Array 1: Broken

This is the first of several implementations of the double-bounded array. It mostly works, but has a problem that we will examine later.

#ifndef _BOUNDARR_H_ #define _BOUNDARR_H_ /* * This class sort of implements an array with user-specified bounds. * Subscripting is done with a at() function, and subscripts are * bounds-checked. This is actually a broken implementation since * Objects in this version do not copy correctly. */ #include <iostream> #include <string> #include <stdexcept> #include <memory> #include <algorithm> template <typename T> class BoundArr { public: // Create a new array of the given dimensions BoundArr(int low, int high): m_space(new T[high-low+1]), m_low(low), m_high(high) { } // Convenience for conventional creation. BoundArr(int size): m_space(new T[size]), m_low(0), m_high(size-1) { } // Find out how large this is. int low() const { return m_low; } int high() const { return m_high; } int size() const { return m_high - m_low + 1; } // Subscript the array. The two versions are allowed, and will // be chosen based on the context of use. T &at(int subs) { return m_space[offset(subs)]; } T const &at(int subs) const { return m_space[offset(subs)]; } // Print the array to the stream. void print(std::ostream &out) const; private: std::shared_ptr<T[]> m_space; // Actual storage space for the array. int m_low, m_high; // Bounds // Check the bounds, throw if out, then return the return the offset // in the private array corresponding to sub. int offset(int sub) const; }; // Check that the sub is in range, and throw if it is not. Otherwise, // return the sub adjusted to an offset for subscripting the base array. template <typename T> int BoundArr<T>::offset(int sub) const { if(sub < m_low || m_high < sub) throw std::range_error("Bounds: sub " + std::to_string(sub) + " outside " + std::to_string(m_low) + ".." + std::to_string(m_high)); return sub - m_low; } // Array printer template <typename T> void BoundArr<T>::print(std::ostream &out) const { out << "<" << m_low << "|"; for(int n = 0; n < size(); ++n) { out << " " << m_space[n]; } out << " |" << m_high << ">"; } // This exports the printing function to standard streams by defining // the meaning of << on a stream and a BoundArr to be running the print // method on the array to the stream. template <typename T> inline std::ostream & operator<<(std::ostream &strm, const BoundArr<T> &arr) { arr.print(strm); return strm; } #endif