TITLE: A generalized indicator of failure, or NULL is nothing [ This picks up in the middle of a discussion that began with complaints that STL iterators do not return NULL to indicate failure. It was pointed out that there can be many reasons for failure, and that returning a failure indicator rather than just NULL would handle the general case. One such indicator would be a descriminated union (not supported in C++). -adc ] PROBLEM: fjh@munta.cs.mu.OZ.AU (Fergus Henderson) Yes. I agree entirely that discriminated unions are the right way of handling this sort of thing. The only problem is that C++ doesn't support discriminated unions very well. If you follow this argument to it's logical conclusion, you have to say that even null pointers were a mistake. RESPONSE: James Kanze Aren't they? I've stopped using them, in favor of `Fallible' (e.g.: a function will return `Fallible< char* >', rather than simply `char*', if it can fail). RESPONSE: gustav@morpheus.demon.co.uk (Paul Moore) I've never seen "Fallible". Can you point me to a description, and possibly an implementation? RESPONSE: kanze@us-es.sel.de (James Kanze US/ESC 60/3/141 #40763), 19 Apr 95 [ Barton and Nackmann are the authors of a well-respected book on scientific applications programming in C++. -adc ] Barton and Nackmann. I don't have my copy here, so I cannot give the exact page number, but it is in the index. The idea is really pretty simple. The class `template< class T > class Fallible' associates a bool defining the validity with a value of type T. The default constructor constructs an `invalid' Fallible, a constructor from `T const&' constructs a valid Fallible. Assigning a T to a Fallible also makes it valid. The class contains a conversion operator for T, which throws an exception (or has an assertion failure) if the value is not valid. There is also a function to test validity. As a simple example, imagine strchr using Fallible: Fallible< char* > strchr( char* p , char c ) { Fallible< char* > result ; while ( ! result.isValid() && *p != '\0' ) if ( *p == c ) result = p ; return result ; } In a simple case like the above, a null pointer does an acceptible job, and will certainly be more efficient in terms of runtime. But in the more general case, Fallible is probably more understandable (since it doesn't require a `unique' value), and the efficiency differences will be almost negligible. Even in the above case, Fallible has the advantage that attempting to use the pointer returned by strchr in the case where the character was not found will result in an exception, rather than undefined behavior. The following code is off the top of my head, so some of the details may not be right, but it should be enough to get the general idea: template< class T > class Fallible { public : Fallible() ; Fallible( T const& val ) ; Fallible< T >& operator=( T const& val ) ; bool isValid() const ; operator T() const ; private : T value ; bool valid ; } ; template< class T > Fallible< T >::Fallible() : valid( false ) { } template< class T > Fallible< T >::Fallible( T const& val ) : value( val ) , valid( true ) { } template< class T > Fallible< T >& Fallible< T >::operator=( T const& val ) { value = val ; valid = true ; } template< class T > bool Fallible< T >::isValid() const { return valid ; } template< class T > Fallible< T >::operator T() const { assert( valid ) ; return value ; }