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