TITLE: fallible (Newsgroups: comp.lang.c++.moderated, 3 Feb 97) RDWELLS: rdwells@mmm.com wrote: |> > For example, to search an array (size item_count) for a certain |> > element (identified by item_id) to find its position (item_index): |> > |> > for (i = 0; i < item_count; i++) |> > { |> > if (array[i] = item_id) |> > { |> > item_index = i; |> > break; |> > } |> > } TITTLE: Brad Tittle |> How about: |> |> while (i++< item_id){} |> item_index = i; |> |> Please correct me if I made a mistake, I just prefer to avoid to use |> break and goto. I don't know which one is more efficient. KANZE: James Kanze In this particular case, I'd probably write: int i( 0 ) ; for ( ; array[ i ] != itemId && i < itemCount ; i ++ ) ; if ( i < itemCount ) // We've found what we were looking for. The ordering of the tests is very important. Accessing array[ i ] with i == itemCount is probably undefined behavior. For more complicated cases (nested loops, etc.), I generally use Barton and Nackman's Fallible template: Fallible< ResultType > result ; for ( int i = 0 ; ! result.isValid() && i < itemCount ; i ++ ) { if ( someCondition ) result.validate( whatever ) ; } if ( result.isValid() ) // We've got what we wanted. [ Barnton and Nackman are the authors of the highly acclaimed "Scientific and Engineering C++", a text well worth studying for those programming outside of scientific and engineering disciplines. There is an existing tip on fallible at http://www.ses.com/ ~clarke/cpptips/fallible. Another source is shown below. Below is some more information on the Fallible class, which came from http://wwwatnf.atnf.csiro.au/Software/Analysis/ aips++/docs/aips/implement/Utilities/Fallible.html -adc ] template class Fallible Interface Public Members Fallible() : isValid_p(False) Fallible(const T &value) : value_p(value), isValid_p(True) Fallible(const Fallible &other) : value_p(other.value_p), isValid_p(other.isValid_p) Fallible &operator=(const Fallible &other) ~Fallible() operator T() const T value() const Bool isValid() const Etymology This is to be used for values which might be fallible, i.e. might not be valid. Synopsis This class resembles the one in Scientific and Engineering C++ by Barton and Nackman. While it was written with that book closed, the class is simple enough that resemblances likely remain. This class essentially just holds a value (with automatic conversion) and allows inquiry as to whether the value is valid. If the value is used and is indeed invalid an exception will be thrown. A copy of the value is stored in the Fallible object, so making copies shouldn't be too expensive. It is anticipated that this class will most often be used with built in, or other small, types. Example Suppose we write some code that turns a day/month/year into a day of the week: enum DayName { Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday }; Fallible dayFromDate(uInt day, uInt month, uInt year); // a func. And we also have some other function that needs a day name, for example just prints it: ostream &operator<<(ostream &os, DayName day); // Print name as string Since the automatic conversions are defined, if we are certain that the dates are valid, we can just go ahead and use the value: cout << dayFromData(2, 1, 1962) << endl; // A valid date If, by some chance, you are wrong and a date fails, then an exception will be thrown and a run-time error will occur. If, as is more likely the case, you don't know a priori whether a test will succeed, you can check it: Fallible result = dayFromDate(d,m,y); // who knows if valid? if (result.isValid()) { cout << result << endl; } else { // some corrective action } Motivation The alternatives are to have "special values" (e.g. have an "undefined day" in the enumeration) or return a Boolean, or change a Boolean. While those solutions are often adequate, Fallible can often be more natural.