Summary
The December 2004 issue of the C/C++ Users Journal has just come out and contains an article I wrote "Constrained Value Types using Policies" which discusses how to use policies to define special cases of value type which must conform to specific ranges or sets of values.
Advertisement
A recent article I wrote on constrained value types using policies is now available in the December 2004, issue of C/C++ Users Journal.
A constrained value type is a value type such as an integer or float which must fit a set of constraints. For example a bounded range, values divisible by some factor, etc. A very straightforward example is a double which must be non-negative. Defining such a type can be done as follows:
struct non_negative_double_constraint {
typedef double value;
static void assign(const value& rvalue, value& lvalue) {
if (rvalue < 0.0) { throw 0; }
lvalue = rvalue;
}
};
typedef cv::constrained_value
< non_negative_double_constraint
> non_negative_double;
int main() {
non_negative_double d = 1.0; // fine
d = -1.0; // throws an exception;
}
The non_negative_double_constraint represents the policy. A policy type typically has only static members which are used to define the behaviour of another type. A policy is usually passed as a template argument. Using policies allows the constrained_value type to be as generic as possible. For example the constraint policy may always assign the nearest legal value (a saturation policy), or apply a modulo (e.g. degrees of the circle) or whatever, just use your imagination.
More example of constrained types and the constrained_value source code itself is freely available on my web site cdiggins.com.
Special acknowledgement to Jeff Garland whose work of the same name inspired the article and the type, as well as other members of the Boost community who made several useful and insightful suggestions.
> If I was using this class I'd rather type something like > > typedef cv::constrained_value <double, non_negative> > non_negative_double; > > The underlying data type is separate from the constraint. > So you could use the same constraint code with multiple > types.
Nothing wrong with that approach at all. Another option is to define your constraint policy using an argument for the value and another argument for the behaviour. Either way you type the single line of code though it doesn't change things much.
The reason I chose my approach is that ints can be passed as template arguments allowing me to do things like:
Where the saturating policy reassigns out of range values to the nearest valid value.
> Have you tried anything like this yet: > > typedef cv::constrained_value <int, non_negative> > non_negative_int; > > typedef cv::constrained_value <non_negative_int, odd> > non_negative_odd_int;
I don't understand what you are asking.
> Also what about this:- > non_negative_double d = 10; > d -= x; //what happens if x is 11?
It shouldn't compile because the constrained_value only supports assignments and casts to and from the value type. Check out the constrained_value type at http://www.cdiggins.com/constrained_value.hpp , if you want something more sophisticated it shouldn't be hard for you to implement.