/*
  
  Class Possible<T> and PossibleObj<T>:
    
  Wrappers that explicitly express the validity or
  invalidity of the enclosed objects. This eliminates
  the necessity of objects denoting Null or Invalid states.
  By being explicit it also makes user code less error prone.
  
  Functionally these are like short arrays that hold either 0 or 1 element.

  Douglas Cameron: Genetical.com
  ==============================
    1/1/02  Added streaming operators
    8/23/01 Added PossibleObj<> to avoid compiler warnings.
    4/20/01 used again, added NotPossible.
    5/10/01 Added op-> Nice. This class seems to be handy.
            While working on simple RegExp
    5/12/01 Requiring op T() be replaced by op -> (retiring it). Will break some uses,
            but now have op bool().
    3/5/01  First use
    3/1/01  Written
*/

#include <iostream.h>
#include "General.h"

#define Possible_h

namespace AlphaSquaredLib {

  struct NotPossible_ { };             // syntatic token
  extern NotPossible_ NotPossible;
  extern NotPossible_ NotFound;        // useful synonym

  template <class T>
  struct Possible {
    Possible() : obj(), valid(false) { }
    Possible( const T& t ) : obj(t), valid(true) { }
    Possible( const NotPossible_& ) : obj(), valid(false) { }

    void operator= ( const T& t ) { obj=t; valid=true; }
    void Invalidate() { valid = false; }
    operator bool() const { return valid; }
    // depreciated (not grepable)
      bool operator!() const { return !valid; }
    bool IsValid() const { return valid; } 
    bool Valid() const { return valid; }   // depreciated
    const T& Obj() const { return obj; }
    T&       Obj() { return obj; }

    bool operator==( const Possible<T>& p ) const {
      return (!valid and !p.valid) or obj==p.obj;
      }

    friend ostream& operator<<( ostream& os, const Possible<T>& p );
    friend istream& operator>>( istream& is, Possible<T>& p );

    private:
      bool   valid;
      T      obj;
  };

} // end namespace 

