relational::operator bool()

Douglas Gregor gregod at cs.rpi.edu
Wed Nov 14 18:46:54 CET 2001


On Wednesday 14 November 2001 10:38 am, you wrote:
> Can you please email that patch?  (I'm still trying to grok whether this
> breaks compatibilities.  Binary yes, I guess.)

I've attached the patch against current CVS. It will break binary 
compatibility on some platforms. There is also a source compatibility break 
if one uses:

  relation r = ...;
  if (r == true) ...

If that's a concern, it can be fixed with a few overloads of operator== and 
operator!= for (relation,bool) and (bool,relation).

	Doug
-------------- next part --------------
? GiNaC.spec
? Makefile
? Makefile.in
? aclocal.m4
? config.h
? config.h.in
? config.log
? config.status
? configure
? ginac-config
? ginac-config.1
? libtool
? stamp-h
? stamp-h.in
? stamp-h1
? check/.deps
? check/.libs
? check/Makefile
? check/Makefile.in
? check/checks
? check/checks.out
? check/exam.gar
? check/exams
? check/exams.out
? check/times
? check/times.out
? doc/Makefile
? doc/Makefile.in
? doc/reference/Makefile
? doc/reference/Makefile.in
? doc/tutorial/Makefile
? doc/tutorial/Makefile.in
? ginac/.deps
? ginac/.libs
? ginac/Makefile
? ginac/Makefile.in
? ginac/exprseq.cpp
? ginac/exprseq.h
? ginac/function.cpp
? ginac/function.h
? ginac/input_lexer.cc
? ginac/input_parser.cc
? ginac/input_parser.h
? ginac/libginac.la
? ginac/lst.cpp
? ginac/lst.h
? ginac/version.h
? ginsh/.deps
? ginsh/Makefile
? ginsh/Makefile.in
? ginsh/ginsh.1
? ginsh/ginsh_fcn_help.h
? ginsh/ginsh_op_help.h
? ginsh/ginsh_parser.cc
? ginsh/ginsh_parser.h
? tools/.deps
? tools/Makefile
? tools/Makefile.in
? tools/viewgar.1
Index: ginac/relational.cpp
===================================================================
RCS file: /home/cvs/GiNaC/ginac/relational.cpp,v
retrieving revision 1.40
diff -c -3 -p -r1.40 relational.cpp
*** ginac/relational.cpp	2001/10/27 16:18:57	1.40
--- ginac/relational.cpp	2001/11/14 17:39:56
*************** ex relational::rhs(void) const
*** 233,263 ****
  // non-virtual functions in this class
  //////////
  
  /** Cast the relational into a boolean, mainly for evaluation within an 
   *  if-statement.  Note that (a<b) == false does not imply (a>=b) == true in
   *  the general symbolic case.  A false result means the comparison is either
   *  false or undecidable (except of course for !=, where true means either
   *  unequal or undecidable). */
! relational::operator bool() const
  {
  	const ex df = lh-rh;
  	if (!is_ex_exactly_of_type(df,numeric))
  		// cannot decide on non-numerical results
! 		return o==not_equal ? true : false;
  	
  	switch (o) {
  	case equal:
! 		return ex_to<numeric>(df).is_zero();
  	case not_equal:
! 		return !ex_to<numeric>(df).is_zero();
  	case less:
! 		return ex_to<numeric>(df)<_num0;
  	case less_or_equal:
! 		return ex_to<numeric>(df)<=_num0;
  	case greater:
! 		return ex_to<numeric>(df)>_num0;
  	case greater_or_equal:
! 		return ex_to<numeric>(df)>=_num0;
  	default:
  		throw(std::logic_error("invalid relational operator"));
  	}
--- 233,270 ----
  // non-virtual functions in this class
  //////////
  
+ relational::safe_bool relational::make_safe_bool(bool cond) const
+ {
+   return cond? &safe_bool_helper::nonnull
+              : 0;
+ }
+ 
  /** Cast the relational into a boolean, mainly for evaluation within an 
   *  if-statement.  Note that (a<b) == false does not imply (a>=b) == true in
   *  the general symbolic case.  A false result means the comparison is either
   *  false or undecidable (except of course for !=, where true means either
   *  unequal or undecidable). */
! relational::operator relational::safe_bool() const
  {
  	const ex df = lh-rh;
  	if (!is_ex_exactly_of_type(df,numeric))
  		// cannot decide on non-numerical results
! 		return o==not_equal ? make_safe_bool(true) 
!                                     : make_safe_bool(false);
  	
  	switch (o) {
  	case equal:
! 		return make_safe_bool(ex_to<numeric>(df).is_zero());
  	case not_equal:
! 		return make_safe_bool(!ex_to<numeric>(df).is_zero());
  	case less:
! 		return make_safe_bool(ex_to<numeric>(df)<_num0);
  	case less_or_equal:
! 		return make_safe_bool(ex_to<numeric>(df)<=_num0);
  	case greater:
! 		return make_safe_bool(ex_to<numeric>(df)>_num0);
  	case greater_or_equal:
! 		return make_safe_bool(ex_to<numeric>(df)>=_num0);
  	default:
  		throw(std::logic_error("invalid relational operator"));
  	}
Index: ginac/relational.h
===================================================================
RCS file: /home/cvs/GiNaC/ginac/relational.h,v
retrieving revision 1.33
diff -c -3 -p -r1.33 relational.h
*** ginac/relational.h	2001/08/22 16:11:51	1.33
--- ginac/relational.h	2001/11/14 17:39:56
*************** public:
*** 70,78 ****
  	virtual ex rhs(void) const;
  
  	// non-virtual functions in this class
  public:
! 	operator bool(void) const;
! 	
  // member variables
  	
  protected:
--- 70,93 ----
  	virtual ex rhs(void) const;
  
  	// non-virtual functions in this class
+ 
+ private:
+         // for conversions to boolean, as would be used in an if conditional,
+         // implicit conversions from bool to int have a large number of
+         // undesirable side effects. The following safe_bool type enables
+         // use of relational objects in conditionals without those side effects
+         struct safe_bool_helper {
+           void nonnull() {};
+         };
+ 
+         typedef void (safe_bool_helper::*safe_bool)();
+ 
+         safe_bool make_safe_bool(bool) const;
+ 
  public:
! 	operator safe_bool(void) const;
! 	safe_bool operator!(void) const;
! 
  // member variables
  	
  protected:
*************** protected:
*** 87,92 ****
--- 102,113 ----
  template<> inline bool is_exactly_a<relational>(const basic & obj)
  {
  	return obj.tinfo()==TINFO_relational;
+ }
+ 
+ // inlined functions for efficiency
+ inline relational::safe_bool relational::operator!() const
+ {
+   return make_safe_bool(!static_cast<bool>(*this));
  }
  
  } // namespace GiNaC


More information about the GiNaC-devel mailing list