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