
File: Base_Range.C
  Error messages need to have the COMPLETE class name, and report the
  value in error.  Change ALL methods to take 2 arguments:
  (const char* type, const char* value="")
  And change the text to be something like:
  "%s::Range<>(): Value %s greater than upper-limit",
  type, lower, upper, value).

File: Range.h

  Add the following before the class template:
MACRO Quotify_Arg(arg) {#arg}
template <class Type, Type lbound, Type hbound> Range {
  #undef Range_Name_String
  #define Range_Name_String Quotify_Arg(Range<Type, lbound, hbound>)
}

  Add the following private member function
template <class Type, Type lbound, Type hbound>
char* Range<Type,lbound,hbound>::value_string(const Type& value) {
  ostream str_stream(MSG_MAX, error_msg_buffer);
  str_stream << value;				// "print" value into buffer
  return strdup(error_msg_buffer);
}

  when calling any of the error reporting methods in Base_Range.C,
  use the agrument list (Range_Name_String, this->value_string(value))


  Make the default compare_s slot NULL.  There are two reasons for this,
  1. it's more efficient.
  2. the default compare function is Type##_Range_Compare
     which may not be unique. For example, the following both would
     have the same default range compare function, and the COOL would
     generate two functions with the same name.
        Range<float, 0.0, 3.14> and 
        Range<float, -3.14, 3.14> 
     The linker gets duplicate definition errors when this happens.     

  Range<Type,lbound,hbound> ();			// Simple constructor
  Make this inline.

  Range<Type,lbound,hbound>::Range<Type,lbound,hbound> (const Type& value)
  Instead of checking bounds, call the set method.

  void Range<Type,lbound,hbound>::set (const Type& value) {
  Re-write this as follows:

inline void Range<Type,lbound,hbound>::set (const Type& value) {
  if (this->compare != NULL)			// When Custom compare function
    this->do_compare(value);
  else 						// Normal, fast case
   // check both bounds at once to minimize the amount of inline code
   if (value < this->low_bound || value > this->high_bound)
     this->report_set_error (value);		// Raise exception
  this->data = value;
}

new protected methods:
template <class Type, Type lbound, Type hbound>
void Range<Type,lbound,hbound>::report_set_error (const Type& value) {
  if (value < this->low_bound)
    this->set_low_error (Range_Name_String, this->value_string(value));
  else if (value > this->high_bound)
    this->set_upper_error (Range_Name_String, this->value_string(value));
}
  
template <class Type, Type lbound, Type hbound>
void Range<Type,lbound,hbound>::do_compare (const Type& value) {
  if ((*this->compare_s)(value, this->low_bound) < 0) // Lower bounds check
    this->set_low_error (Range_Name_String, this->value_string(value));
  else if ((*this->compare_s)(value, this->high_bound) > 0) // Upper bounds
    this->set_upper_error (Range_Name_String, this->value_string(value));
}


When cfront 2.0 comes along, put the value of Range_Name_String in a
static slot.  This keeps application functions from allocating their
own copy of this static string.
