From: Robert Kawulak (kawulak_at_[hidden])
Date: 2005-09-29 14:26:16
> From: Rob Stewart
> > > [sig?]
> > What's this?
> My guess is he's calling your attention to the lost attribution.
Ah, sorry! Now I'll remember. :)
> > It's not a static created only for initialisations. Bounds
> > functions min_value() and max_value() create function-scope
> static objects
> > and return them, this way the objects aren't being created
> every time the
> > functions are called (and they're called very often, so I
> think this is
> > reasonable for non-integral types). And initialize() only returns
> > min_value() and that's it.
> Once you go with a function local static, you have to worry about
> thread safety.
Even though the local statics are constant? Then the only problem would be
initialisation, but doesn't compiler take a proper care of this in
> In the simpler range bounded approach, the type
> includes the boundaries, so there's no need for statics. It
> would only be the more complicated bounding policies that might
> have need for this behavior. Thus, don't force the creation of
> statics in your design. Ensure that if they are used, it is the
> choice of the policy writer.
Well, it's not forced - one may easily supply his own bounds specifying
policy that pass bounds by value.
Actually, in my implementation it depends on the underlying type. If it's
integral, then bounds are returned by value. If it's not, the min_value()
function looks something like this:
static const value_type & min_value()
static const value_type v = MinValueGenerator()();
Is there really something that wrong with this design? Is there any danger
out there because of using function-scope const static object? It just
seemed much better to me - the value is constructed only once, and every
next time min_value() takes only one comparison (static initialisation
check) and returning a reference. In return-by-value case every call results
1) creation of generator object (in most cases optimised away)
2) call of generator's call operator which results in construction of new
3) copying the object on return and destructing it (may be optimised away by
RVO, but not always)
4) eventually copying and destructing the object again and again as it's
passed by value
*) using the object, for example when comparing it with the value you try to
assign to check whether the value lays within bounds, in every assign there
are two such checks - multiply all the operations by 2
5) destructing the object
I can see no con in using function-scope const statics here and a huge pro -
efficiency. And I don't consider it as premature optimisation - it rather
seems to me as avoiding premature pessimisation.
> > > Why not just 'constrained'? ie. constrained<int>?
Well, this wouldn't be
bounds_specifiers::static_bounds<int, 0, 10> > >
But I like the concise name 'constrained' anyway.
> The library name should probably be "Constrained," the
> namespace, "constraineds," and the type, "constrained," if you go
> this route. (That's in keeping with Boost.Tuple, which uses the
> "tuples" namespace and the "tuple" type.)
> If you call it the "Constrained Types" library, and use the
> namespace "constrained_types," does "constrained" for the type
> name fit with Boost prior art and intention? Those names sound a
> lot better, so that may be sufficient justification, but I don't
> want to presume this approach is acceptable to Boost as a whole.
For me the latters also sound better, what do you people think?
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk