Boost logo

Boost :

From: Paul Moore (gustav_at_[hidden])
Date: 2001-01-16 16:15:16


On 15 Jan 2001, at 22:02, Jens Maurer wrote:

> Jens Maurer wrote:
> > Ok, now we have a nice technical problem to solve: How to allow
> > for a rational(long) constructor which works even for rational<long>,
> > where we have to avoid ambiguities with the copy constructor.
>
> Option 1: Use template specialization
>
> Define specializations for rational<long> and rational<unsigned long>,
> e.g. (abbreviated):

Blech. Duplicate more or less the whole class just for one
constructor? I'd rather not do this.

> Option 2: Same as option 1, but define everything except the
> constructors in a base class:

Better, but it feels untidy. Why use inheritance for a simple class
like this? I *assume* that there is no runtime overhead with this
technique? Or is there - does the derived class take up extra space
even though it has no data members?

Regardless, it feels overcomplicated.

> Hm... Looks like explicit specializations are required, because
> we need to do away with one offending constructor.

I'm not sure I follow this comment.

> Instead of long/unsigned long you may consider using boost::intmax_t
> and boost::uintmax_t from boost/cstdint.hpp, although integer_test.cpp
> does not seem to work on Win32 / MSVC 6.0sp4 / STLport 4.0.

Blech. More MSVC breakage. (Am I right in reading this as
boost/cstdint.hpp is not going to work right on MSVC?)

> Completely unrelated:
> We should probably split
> rational(IntType n = 0) : num(n), den(1) {}
> into two constructors, because the default-argument version needs an
> implicit conversion from int to IntType, which may not exist.

OTOH, doesn't

    rational() : num(0), den(1) {}

still need an implicit conversion from int to IntType? Hmm, no. It's
an explicit construction. Is that better? What about my proposed

    rational(IntType n = IntType(0)) : num(n), den(1) {}

At some point in this, we're going to get to a point where I think it's
getting silly. I keep reminding myself that this is meant to be a
general-use class. For specialist use, there are better rational
implementations.

std::complex explicitly states that it is only defined to "work" for
the builtin float types. The only reason I don't do the same is
because I want to leave the possibilty of using an unlimited-
precision integer type open. I am *not* trying to cover all possible
types.

If boost had an unlimited-precision integer type, I'd be quite happy
saying that rational<T> is only supported for T either a built in
integer type, or boost::integer. Maybe I'd better just write
boost::integer and leave it at that.

Sorry, that sounded petty. But I really don't think that trying to
make rational<> all things to all men is either what I intended, nor
is it practical. Next thing, we're going to get performance
questions, like "what if IntType has fast multiplication but division is
extremely slow?"

What would people think of the idea of my implementing a
boost::integer type (NB - it will be on the same basis as
boost::rational - "a good compromise for general use" rather than
the ultimate in performance or whatever) and then stating that
rational<> is not supported for types other than this or built-in
integers?

Basically, I don't object to working on ensuring that rational<>
works for a user-defined unlimited-precision integer type. But I want
to focus on *one* such type, and not try to cover the whole range of
possibilities. The possible trade-offs are too varied, and will leave
no usable "lowest common denominator" for rational<> to assume.
(The "no default conversion from int" issue is getting close to that).
I'd like to hold off on the "what if IntType does X?" questions until
we have an accepted boost unlimited-precision integer type.

This isn't to say that the current discussions have been useless.
Far from it - without Stephen Silver's original work trying rational<>
with his integer type, none of these issues would have surfaced.
But I think that now is the time to step back and put together a
concrete proposal for a boost unlimited-precision integer type.

Anyone with alternative such types can then compare with the
boost one and explore the reasons for the trade-offs. With that as a
basis, we can more easily decide how much effort it is sensible to
put into making sure boost::rational<> supports that alternative
type.

Comments?

Paul.

PS There have been a number of other points raised on these
threads over issues NOT related to the use of a user-defined
IntType. I will incorporate all of those points regardless of what I
end up doing on user-defined types.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk