One of the hardest issues I had while porting WinROTT from C to C++ was what to do with the enum dirtype.
(See here for a discussion.) Dirtype is a typedef in the WinROTT C program:
typedef enum {
east,
northeast,
north,
northwest,
west,
southwest,
south,
southeast,
nodir
} dirtype;
The original author of ROTT was working in C, which allows enums like dirtype to be handled like int. This means that common operators like the prefix and postfix increment operator (++) are allowed on variables of type enum.
As a work around in C++, I substituted the following code to get keep things working while I moved .c files to .cpp files. Here's the stopgap code I employed to replace the above enum:
#define east 0
#define northeast 1
#define north 2
#define northwest 3
#define west 4
#define southwest 5
#define south 6
#define southeast 7
#define nodir 8
typedef short dirtype;
While this is dangerous code, it allowed me to compile the existing mixed C/C++ code and test the program logic.
Finally, I've had time to design a new class and enum combination that utilizes modern C++ code and required only minimal changes to the existing source code that uses dirtype. (The only changes required are a couple of casts of variables to int. Here's the new class. It's a whopper in size. I had to implement a large number of operator overrides in order to handle all situations I found in the ported C++ code. The class is a much safer implementation. All operator overloads are guaranteed to return a direction know to the
enum direction. The old C code and my hack did not check to determine if any sort of operation resulted in a value outside the range of enum values.
(This class and its friend functions offer a good example of how to overload operators.)
enum direction:int {east,northeast,north,northwest,west,southwest,south,southeast,nodir};
struct dirtype
{
private:
direction value;
public:
// Constructors
dirtype() { value = nodir; }
dirtype (direction d) { value = d; }
dirtype (int d) { value = (direction) (d % 9); }
// Assignment operators
inline dirtype& operator= (const dirtype &pval)
{
this->value = pval.value;
return *this;
}
inline dirtype& operator= (const direction pval)
{
this->value = pval;
return *this;
}
inline dirtype& operator= (const int pval)
{
this->value = (direction)(pval % 9);
return *this;
}
inline dirtype& operator= (const short pval)
{
this->value = (direction)(pval % 9);
return *this;
}
inline dirtype& operator= (const unsigned char pval)
{
this->value = (direction)(pval % 9);
return *this;
}
inline dirtype& operator= (const char pval)
{
this->value = (direction)(pval % 9);
return *this;
}
// Casting operators
inline operator char() { return this->value; };
inline operator unsigned char() { return this->value; };
inline operator short() { return this->value; };
inline operator int() { return this->value; };
inline operator direction() { return this->value; };
// Addition operators
friend dirtype operator+ ( const dirtype &rs, const int i);
friend dirtype operator+ ( const dirtype &rs, const dirtype &ds);
inline dirtype& operator+= (dirtype &pval)
{
int dir = this->value;
dir += pval.value;
this->value = (direction) (dir % 9);
return *this;
}
inline dirtype& operator+= (const direction pval)
{
int dir = this->value + (int) pval;
this->value = (direction) (dir % 9);
return *this;
}
inline dirtype& operator+= (const int pval)
{
int dir = this->value + pval;
this->value = (direction)(dir % 9);
return *this;
}
// Multiplication operators
friend dirtype operator* (const dirtype &rs, const int i);
friend dirtype operator* (const int i, const dirtype &rs);
inline dirtype& operator*= (const dirtype &pval)
{
int dir = this->value;
dir *= (int) pval.value;
this->value = (direction) (dir % 9);
return *this;
}
inline dirtype& operator*= (const direction pval)
{
int dir = (int) this->value * (int) pval;
this->value = (direction) (dir % 9);
return *this;
}
inline dirtype& operator*= (const int pval)
{
int dir = (int) this->value * pval;
this->value = (direction)(dir % 9);
return *this;
}
// Shift
friend dirtype operator<< (const dirtype &rs, const int i);
friend dirtype operator>> (const dirtype &rs, const int i);
inline dirtype& operator<<= (const int pval)
{
int dir = this->value << pval;
this->value = (direction)(dir % 9);
return *this;
}
// Increment
dirtype& operator++ ()
{
int dir = this->value + 1;
this->value = (direction)(dir % 9);
return *this;
}
dirtype operator++ ( int )
{
dirtype temp = *this;
++*this;
return temp;
}
// Equality
friend bool operator== (const dirtype &rs, const int i);
friend bool operator== (const int i, const dirtype &rs );
friend bool operator== (const dirtype &rs, const direction d);
friend bool operator== (const direction d, const dirtype &rs );
friend bool operator== (const dirtype &rs, const dirtype &ds );
friend bool operator== (const int i, const direction rs );
// Inequality
friend bool operator!= (const dirtype &rs, const int i);
friend bool operator!= (const dirtype &rs, const byte i);
friend bool operator!= (const dirtype &rs, const short i);
friend bool operator!= (const int i, const dirtype &rs );
friend bool operator!= (const dirtype &rs, const direction d);
friend bool operator!= (const direction d, const dirtype &rs );
friend bool operator!= (const dirtype &rs, const dirtype &ds );
};
inline dirtype operator<< (const dirtype &rs, const int i)
{
return dirtype(((int)rs.value << i) % 9);
}
inline dirtype operator>> (const dirtype &rs, const int i)
{
return dirtype(((int)rs.value >> i) % 9);
}
inline dirtype operator* (const dirtype &rs, const int i)
{
return dirtype(((int)rs.value * i) % 9);
}
inline dirtype operator* (const int i, const dirtype &rs)
{
return dirtype(((int)rs.value * i) % 9);
}
inline dirtype operator+ (const dirtype &rs, const dirtype &ds)
{
return dirtype(((int)(rs.value + ds.value)) % 9);
}
inline dirtype operator+ (const dirtype &rs, const int i)
{
return dirtype(((int)rs.value + i) % 9);
}
inline bool operator== (const dirtype &rs, const int i)
{
return (int) rs.value == i;
}
inline bool operator== (const int i, const dirtype &rs)
{
return (int) rs.value == i;
}
inline bool operator== (const dirtype &rs, const direction d)
{
return rs.value == d;
}
inline bool operator== (const direction d, const dirtype &rs)
{
return rs.value == d;
}
inline bool operator== (const dirtype &rs, const dirtype &ds )
{
return rs.value == ds.value;
}
inline bool operator== (const int i, const direction d)
{
return i == (int) d;
}
inline bool operator!= (const dirtype &rs, const int i)
{
return (int) rs.value != i;
}
inline bool operator!= (const dirtype &rs, const short i)
{
return (int) rs.value != (int) i;
}
inline bool operator!= (const dirtype &rs, const byte i)
{
return (int) rs.value != (int) i;
}
inline bool operator!= (const int i, const dirtype &rs)
{
return (int) rs.value != i;
}
inline bool operator!= (const dirtype &rs, const direction d)
{
return rs.value != d;
}
inline bool operator!= (const direction d, const dirtype &rs)
{
return rs.value != d;
}
inline bool operator!= (const dirtype &rs, const dirtype &ds )
{
return rs.value != ds.value;
}