
Hi,
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 specifier's 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 multi-threaded implementation?
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()(); return v; } 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 in: 1) creation of generator object (in most cases optimised away) 2) call of generator's call operator which results in construction of new object 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 constrained<int> but constrained< bounded_policies::error< 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? Best regards, Robert