~/ntl-11.4.2/doc/Lazy.cpp.html

    /***************************************************************************

    Lazy<T>: 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 solution.

    Usage:

       Lazy<T> obj; // declaration of the lazy object

        ...

       do {
          Lazy<T>::Builder builder(obj);
          if (!builder()) break; // if we are not building, the break out

          UniquePtr<T> p;  // create a pointer

             ...

          builder.move(p); // move p into the object to complete the initialization
                           // We can then complete the initialization process.
       } while(0);  // When this scope closes, the object is fully initialized.
                    // subsequent attempts to build the object will yield
                    // !builder.built()

       T objCopy = *obj;   // *obj returns a read-only reference
                           // one can also use -> operator

    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.

    NOTE: if p is null in builder.move(p), the object is still considered
    built.

    ****************************************************************************/

    template<class T, class P=DefaultDeleterPolicy>
    class Lazy {
    public:
       Lazy();

       Lazy(const Lazy&);
       Lazy& operator=(const Lazy&);
       // deep copies using T's copy constructor
       // EXCEPTIONS: may throw (but provides strong ES guarantee)

       const T& operator*()  const;     // pointer access
       const T* operator->() const;
       const T* get() const;

       operator fake_null_type() const;
       // allows test against 0

       ~Lazy();

       kill();  // destroy and reset

       bool built() const; // test if already built

       class Builder {
          Builder(const Lazy&);
         ~Builder()

          bool operator()() const; // test if we are building

          void move(UniquePtr<T,P>&);
          // EXCEPTIONS: may throw an exception if the move is not allowed
          // (i.e., not building or already moved).
          // Provides strong ES guarantee.
       };
    };

    // 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 Lazy
    // 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.

    // NOTE: The optional parameter P is used as in the specification
    // of the UniquePtr class.  The default should work fine in
    // most cases.  It was introduced mainly to allow for the PIMPL
    // paradigm.