Listing 5: Merging subarrays, template metaprogramming, and expression templates into a full implementation of the Array class

#include <stddef.h>
#include <iostream.h>
     
//Expressions//////////////////////
template <class E, int SPACE>
class Expr {
public:
  Expr(const E& e): _e(e) {}
     
  void operator()(size_t** x)const
  { _e(x);}
     
private:
  E _e;
};
     
class Dim {
public:
  Dim(size_t x):_value(x) {}
  void operator()(size_t** x)const
  {
    **x = _value;
    (*x)++;
  }
  size_t operator()(void) const
  { return _value; }
     
private:
  size_t _value;
};
     
template <class A, class B>
class ToupleExpr {
public:
  ToupleExpr(const A& a,
    const B& b): _a(a), _b(b) {}
     
  void operator()(size_t** x)const
  { _a(x);_b(x);  }
     
private:
  A _a;  B _b;
};
     
template <class A, int SPACE>
Expr<
  ToupleExpr<Expr<A, SPACE>, Dim>,
  SPACE+1 >
operator<<
  (const Expr<A, SPACE>&lhs,
  const Dim& rhs)
{
  typedef
    ToupleExpr<Expr<A, SPACE>, Dim>
    ExprT;
     
  return Expr<ExprT, SPACE+1>
    (ExprT(lhs, rhs));
}
     
Expr<ToupleExpr<Dim, Dim>, 2 >
operator<<
  (const Dim& lhs, const Dim& rhs)
{
  typedef
    ToupleExpr<Dim, Dim> ExprT;
     
  return Expr<ExprT, 2>
    (ExprT(lhs, rhs));
}
     
//Array Classes////////////////////
template<class T, int SPACE>
class Array {
public:
  template <class DE>
    Array(Expr<DE, SPACE> expr)
  {
    size_t dims[SPACE];
    size_t *pdims = dims;
    expr(&pdims);
     
    for(size_t i = SPACE; i--;)
      if (!dims[i])
      { /*handle error*/ }
     
    dim = dims[0];
     
    data = new
      Array<T, SPACE-1>[dim];
     
    for(i = dim; i--;)
      data[i].init(&dims[1]);
  }
     
  ~Array(){ delete [] data; }
     
  Array<T, SPACE-1>&
    operator[](size_t index)
  {
    if (index >= dim)
    { /*handle error*/ }
    return data[index];
  }
     
  const Array<T, SPACE-1>&
    operator[](size_t index)const
  {
    if (index >= dim)
    { /*handle error*/ }
    return data[index];
  }
     
  size_t operator()(void) const
  { return dim; }
     
private:
  Array(): data(NULL), dim(0) {}
     
     
  void init(size_t* dims)
  {
    dim = dims[0];
     
    data = new
      Array<T, SPACE-1>[dim];
     
    for(size_t i = dim; i--;)
      data[i].init(&dims[1]);
  }
     
private:
  size_t dim;
  Array<T, SPACE-1>* data;
friend class Array<T, SPACE+1>;
};
     
template<class T>class Array<T, 1>{
public:
  Array(Dim expr)
  {
    dim = expr();
    completeInit();
  }
     
  ~Array(){ delete [] data; }
     
  T& operator[](size_t index)
  {
    if (index >= dim)
    { /*handle error*/ }
    return data[index];
  }
     
  const T&
  operator[](size_t index)const
  {
    if (index >= dim)
    { /*handle error*/}
    return data[index];
  }
     
  size_t operator()(void) const
  { return dim; }
     
private:
  Array(): data(NULL), dim(0) {}
     
  void init(size_t* dims)
  {
    dim = dims[0];
    completeInit();
  }
  void completeInit(void)
  {  data = new T [dim];}
     
private:
  size_t dim;
  T* data;
friend class Array<T, 2>;
}
     
//Sample Main//////////////////////
int main (void)
{
  size_t a, b, c;
  cin >> a >> b >> c;
     
  Array<int, 3>A1(Dim(a)<< b << c);
     
  for(a=0; a<A1(); a++)
    for(b=0; b<A1[a](); b++)
      for(c=0; c<A1[a][b](); c++)
        A1[a][b][c] = 0;
     
  Array<float, 1> A2(5);
  A2[2] = 3.14159;
       return 0;
}
     
/* End of File */