LazyTable<T,MAX>: template class for lazy initialization of objects whose
values do not change after initialization.  In a multi-threaded environment,
this makes use of "double checked locking" for an efficient, thread-safe


   LazyTable<T,MAX> tab; // declaration of the lazy table, 
                         // with max size == MAX


   do {
      LazyTable<T,MAX>::Builder builder(tab, n); // request length n
      long amt = builder.amt();
      if (!amt) break;      

      ... initialize elements i = n-amt..n-1 
          using builder.move(p), where p is a UnqiuePtr<T>
          note that each move application appends one element
   } while(0);    // When this scope closes, 
                  // the table is fully initialized to length n

   const T* val = table[i];  // read-only access to table elements 0..n-1

It is important to follow this recipe carefully.  In particular,
the builder must be enclosed in a scope, as it's destructor
plays a crucial role in finalizing the initialization.


template<class T, long MAX>
class LazyTable {

   const T * const  operator[] (long i) const;
   // element access -- currently no range checking

   long length() const;
   // current table length

   class Builder {
      Builder(const LazyTable&, long request);
      // EXCEPTIONS: may throw an exception if request is out of range
      // or if alocation of table fails


      long amt() const;

      void move(UniquePtr<T>& p);
      // EXCEPTIONS: throws exception of move is not allowed.
      // Provides strong ES guarantee.

   LazyTable(const LazyTable&);             // disabled
   LazyTable& operator=(const LazyTable&);


// EXCEPTIONS: except where noted, no exceptions are thrown

// NOTE: For more on double-checked locking, see
// http://preshing.com/20130930/double-checked-locking-is-fixed-in-cpp11/

// NOTE: when compiled with the NTL_THREADS option, the LazyTable
// class may contain data members from the standard library
// that may not satisfy the requirements of the Vec class
// (i.e., relocatability).  One can wrap it in a pointer 
// class (e.g., CopiedPtr) to deal with this.