 # Boost :

From: Stephen Silver (boost_at_[hidden])
Date: 2001-01-11 17:01:27

I've been trying out the Boost rational number library, and have come
across some problems. These problems are only encountered when using
a user-defined type (in my case, an arbitrary-precision integer type)
as the template argument.

The first problem is fairly minor. The gcd() function template in
rational.hpp is documented as working for "any types for which the
following operations are defined: =, +=, *=, /=, %, <". However, it
contains the line

while (m) {

so it also requires that implicit conversion to bool be possible. This
is not a very desirable requirement, because user-defined conversion
functions that convert to built-in types are not very safe (due to the
possibility of the conversion happening in contexts where it was not
anticipated). Note that the above line could be changed to

while (!!m) {

which would have the advantage that it could work by means of operator!
instead of requiring implicit conversion to bool.

The second problem will arise with any user-defined integer type that is
used with boost::rational. Suppose Integer is such a type, and we have:

rational<Integer> r(2);
r += 2;

This simple operation will not compile, because it requires the
application of two successive implicit user-defined conversions (int ->
Integer -> rational<Integer>). This means that it's necessary instead
to write

r += Integer(2);

This gets pretty cumbersome when you have to do it a lot. And you
usually do have to do it a lot, because it applies to just about every
operator that boost::rational defines. The problem can be cured by
adding a template constructor like this:

template <class T> rational(T n) : num(), den(1) { num = n; }

(I've set the value of 'num' by assignment rather than initialization
because initialization could make use of a constructor that had been
declared explicit, which may not be desirable - although it's hard to
think of a realistic situation in which it would cause a problem.)

Lastly, there is a question of efficiency. The 'assign' member function
and two of the constructors take arguments of type IntType. For use with
user-defined integer types it would be better to have arguments of type
const IntType&. Perhaps the choice between IntType and const IntType&
should be made to depend upon the type (using boost::is_standard_integral,
for example).

Stephen Silver