[comp.sys.mac.programmer] C++ 2.0 vs 2.1 bug? repost

rae@gpu.utcs.toronto.edu (Reid Ellis) (12/21/90)

I posted the following earlier, but I gave it a distribution of "local" by
mistake.  Sorry if anyone sees this twice!
---
I've been trying to create pseudo-base-types -- that is, classes which emulate
almost all of the behaviour of a base type -- and have run into what appears
to be a bug.

When I compile the source below on an SGI machine, I have no problem.  If I
compile it on a Macintosh, I get the error shown below.  It looks as if the
compiler is trying to cast a double to an int for some reason.  Can't figure
why, since both the parameter and the expected return value are both
unambiguously double.

File "fakeInt.cp"; line 48 # error: two standard conversions possible
     for abs():  double (double ) and  int (int )

Here's my cfront version:
<< CFront Version 1.0 (9/11/90; AT&T 2.0) *Apple Computer, Inc. 1989-90 >>
                                          ^-- Mac '(c)' character

Note that on an SGI, the "#expr" preprocessor directive does not work, thus
the #ifdef's..

---8<-----c-u-t-----h-e-r-e------->8---------
#include <stream.h>

#ifdef sgi
#   define try(expr) \
        if(expr) cout << "yes "; else cout << "no  "; cout << "expr \n" ;
#   define show(type, expr) \
        cout << "expr = " << (type &)(expr) << '\n';
#else
#   define try(expr) \
        if(expr) cout << "yes "; else cout << "no  "; cout << #expr "\n" ;
#   define show(type, expr) \
        cout << #expr " = " << (type &)(expr) << '\n';
#endif

inline double abs(double d) { return (d >= 0.0) ? d : -d; }
inline int    abs(int    d) { return (d >= 0.0) ? d : -d; }

struct Tint
{
        Tint() {}
        Tint(const int &i)  : value(i) {}
        Tint(const Tint &t) : value(t.value) {}

        operator int &()
                { return value; }
        int operator==(const Tint &t) const
                // this is a bit whimsical ...
                { return abs(value - t.value) <= 1; }
        int operator==(const int &i) const
                { return value == i; }
private:
        int value;
};

struct Tdouble
{
        Tdouble() {}
        Tdouble(const double &d)
                : value(d) {}
        Tdouble(const Tdouble &d)
                : value(d.value) {}

        static const double kEpsilon;

        operator double &()
                { return value; }
        int operator==(const Tdouble &d) const
                { return (abs(value - d.value) < kEpsilon); } // <=== line 48
        int operator==(const double &d) const
                { return value == d; }
private:
        double value;
};

const double Tdouble::kEpsilon = 0.1;

const double kInit = 1.0;
const double kInit2 = 1.003;

void main()
{
        int i1 = 1;
        int i2 = 2;
        Tint x1 = 1;
        Tint x2 = 2;
        // if I try saying "d1 = 1.0" below, it complains about
        // "cannot make a Tdouble from a long double"..
        Tdouble d1 = kInit;
        Tdouble d2 = kInit2;

        show(int, i1);
        show(int, i2);
        show(int, x1);
        show(int, x2);
        show(double, d1);
        show(double, d2);

        try(i1 == x1);
        try(x1 == x2);
        try(x2 == x1);
        try(d1 == d2);

        d2 += 0.1;

        show(double, d2);
        try(d1 == d2);
}