The header file convert.H
supplies several conversion functions and the
CheckedCast
template. All the conversion functions are called convert
;
they attempt to assign the value of the second argument to the first argument.
If the attempt succeeds, they return true
, otherwise they return false
.
The value of the first argument may be modified even when false
is returned.
Here is a summary of the conversions currently offered:
"to" type | "from" type | notes |
---|---|---|
(unsigned) long | ZZ | |
(unsigned) int | ZZ | |
string | ZZ | opt. 3rd arg is base (2--36) |
ZZ | string | opt. 3rd arg is base (2--36) |
ZZ,ZZ | double | produces numerator,denominator |
double | ZZ | |
double | ZZ,ZZ | input is numerator,denominator |
long | unsigned long | |
long | unsigned int | |
long | unsigned short | (always succeeds) |
long | unsigned char | (always succeeds) |
Conversion from ZZ
to string
may return false (e.g. if memory is
insufficient). Conversions to and from string
accept a third argument
indicating the base (between 2 and 36). By default the standard C
convention for specifying the base (8/10/16) is used when converting from
a string: viz. if the string starts "0x" (or "0X") then base
=16,
otherwise if the string starts with "0" then base
=8, otherwise
base
=10.
Specifying a base outside the permitted range will throw ERR::BadNumBase
.
Conversion to a double
fails if overflow occurs. In contrast, underflow
does not cause failure, and the converted value is simply zero.
There is a templated class called CheckedCast
; it is roughly
analogous to static_cast
. The constructor uses the functions
convert
to perform the actual cast; if convert
indicates that the
value could not be converted (i.e. returns false
) then an exception
is thrown CoCoA::ERR::BadCheckedCast
. For example,
CheckedCast<char>(257, "example")
will throw the exception (saying
that it occurred in "example"). Note that the class name is not
checked_cast
to emphasise that it is not a built in cast.
Only some combinations of convert
functions are present so far. The
C++ standard guarantees that all values an unsigned short
can take will
fit into a long
, so the conversion always succeeds; similarly for the
type unsigned char
.
The class CheckedCast
has a single template argument, and the constructor
has a separate template argument to allow the "natural syntax" like that of
static_cast
. I used a class rather than a templated function because a
function would have required the user to specify two template arguments
(i.e. "unnatural syntax"). I don't know if this is the best way to achieve
what I want, but it is simple enough that there are "obviously no deficiencies".
Getting an exception clean implementation for the conversion of a ZZ
to a
string
was not entirely simple, but I do not see how to do it better given
the interfaces to GMP and string
.
The convert
functions are a hotch potch, but how can it be done better?
The implementation of convert(string&, const ZZ&)
is not very efficient
(neither in terms of speed nor in terms of space used).
Should there be a single argument constructor for CheckedCast
?
I keep forgetting to supply the second arg, and the compiler then produces some
unhelpful error message.
BOOST has something like CheckedCast
, perhaps I should use that.
Does operator T
for CheckedCast
make a useless copy?
Should conversion to double
ignore underflow, or should it say that
the conversion failed?