#include // HACK AROUND g++'s INABILITY TO THROW EXCEPTIONS ON SOME MACHINES #define throw(ex) { cerr << "Threw " #ex << endl; exit(1); } // BASE CLASS class Failure { public: Failure(bool status = false) : myStatus(status) , myChecked(false) {} bool IsValid() const { myChecked = true; return myStatus; } operator bool (void) const { return IsValid(); } bool Failed() const { return !IsValid(); } protected: void CheckStatus(void) const { if (!myStatus && !myChecked) { myChecked = true; throw(Failure()); } } void SetStatus(bool status) { myStatus = status; myChecked = false; } bool myStatus; mutable bool myChecked; }; // PROXY CLASS template< class DataType > class Fallible : public Failure { public : Fallible(void) {} Fallible(const Fallible & fb, bool status) : Failure(status) , myValue(fb.myValue) {} Fallible(const DataType& value) : Failure(true) , myValue(value) {} Fallible& operator=(const DataType & value) { myValue = value; SetStatus(true); return *this; } operator DataType() const { CheckStatus(); return myValue; } friend istream& operator>>(istream& is, Fallible& f) { DataType val; if (is>>val) { f = val; } else { f.SetStatus(false); } return is; } friend ostream& operator<<(ostream& os, const Fallible& f) { f.CheckStatus(); return os << f.myValue; } friend Fallible operator<(const Fallible& a, const Fallible& b) { return Fallible(b, a.IsValid() && b.IsValid() && a.myValue < b.myValue); } friend Fallible operator|(const Fallible& a, const Fallible& b) { if (a.IsValid()) { return a; } else { return b; } } friend Fallible operator|(const Fallible& a, const DataType& b) { if (a.IsValid()) { return a; } else { return b; } } private : DataType myValue; }; //template <> Fallible operator/ (const Fallible& n, const Fallible& d) { if ((double)d==0) return Fallible(); return (double)n / (double)d; } int main(void) { Fallible n; Fallible d; cout << "Enter n,d: "; cin >> n >> d ; double quotient = n/d | d/n | -1; cout << "quotient was: " << quotient << endl; }