Boost logo

Boost :

From: Rob Stewart (stewart_at_[hidden])
Date: 2005-09-16 17:22:12


From: "Matt Doyle" <mdoyle_at_[hidden]>
> > From: boost-bounces_at_[hidden]
> > [mailto:boost-bounces_at_[hidden]]On Behalf Of Rob Stewart
> > From: "Matt Doyle" <mdoyle_at_[hidden]>
> > > > From: "michael toksvig" <michaeltoksvig_at_[hidden]>

Please don't overquote.

> > To be certain we're talking about the same thing, Michael and I
> > have been discussing the result of a computation. Built-in types
> > regularly undergo promotions when participating in such
> > expressions, so the question is whether something similar should
> > happen for a checked integral class and what form it should take.
> >=20
> > Michael was positing that the result type should account for the
> > full range of values possible from the computation. I argued
> > against that.
> >=20
> > I should also point out that built-in types don't behave that
> > way; they can overflow silently, but they don't magically gain
> > range. (The analogy isn't strong, but has some bearing, I
> > think.)
>
> I think we are talking about the same thing but from different angles, =
> consider this simple case;
>
> typedef constrained_value<0, 10, policy> MyCV;
> MyCV a =3D 6;
> MyCv b =3D 8;
> MyCv c =3D a + b; // Should fail
>
> If the user wants "c" to be able to hold the result of "a + b" he should =
> define a new type that would accommodate it.

If MyCV::operator + returns MyCV, then a + b won't work, but the
overflow is only detected at runtime. If MyCV::operator +
returns a new type that computes the return type as having a
different range (0-20, in this case), then any two MyCV's can be
added without error. The question is what happens to the result.

In your example, the result is assigned to a MyCV, so the range
of the result is constrained, at runtime, to 0-10, regardless of
the result's type. That's MyCV's job.

Either Michael's or my notion of the return type will give you
the same result, at least if there is a converting constructor to
account for Michael's approach. That is, MyCV would need a
constructor template that accepts other checked types so long as
the ranges aren't completely incompatible. For example, you
wouldn't want the compiler to allow construction of a MyCV from a
checked type with range 20-100.

Getting back to your example, that converting constructor could
accept the result because the computed range, 0-20, has values
that will fit in MyCV's range. Whether the actual value assigned
at runtime satisfies the range check is a separate matter. For
your example, the result, 14, exceeds MyCV's maximum, so you'd
get a runtime error.

The real difference then, arises with how you use the result of a
computation. If you pass it to a function template, for example,
our approaches would result in different instantiations. My
approach would retain the original range checking (0-10), whereas
Michael's approach would have a new range (0-20). That's where I
question the validity of his approach.

If the two types were passed to a function that expected a MyCV,
then it plays out the same as your example.

> We are on the same page aren't we?

Are we?

-- 
Rob Stewart                           stewart_at_[hidden]
Software Engineer                     http://www.sig.com
Susquehanna International Group, LLP  using std::disclaimer;

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