I admit it, I’m lurking on the boost developer mailing list. Most of what’s sent there goes past me, I don’t really feel I have the time to read it all. And sometimes I even post drivel there, usually only to be reminded that I hadn’t paid attention to detail. Such is my lot.
But there was a recent bit of activity on the mailing list that I wanted to share with you, because it was about a constrained value library about to be submitted for review. In the boost world, new libraries are submitted for review, and the results of the review determine whether or not the library is included.
Highly fascinating stuff, if only because Fhtagn! has included pretty much the same functionality for a while now.
So naturally I took a look at the submission, if only to determine whether or not it’s good enough to drop Fhtagn!’s restricted data types in favour of boost’s constrained values. Turns out that I won’t be doing that.
But first, let’s take a brief look at what this sort of code does. I’ll use Fhtagn!’s version, because, well, you’re here already. But note that I’ll use restricted/constrained and restriction/constraint interchangeably in the text below.
The idea is to place constraints on the values that a value type can take. Fhtagn!’s approach was originally inspired by the D language’s approach to design by contract. D allows a function to define a set of constracts, such as the range of values a parameter may take, and throws an exception if that contract is broken.
By associating this sort of contract not with a function, but with a data type, you gain more flexibility, while retaining the ability to define function prototypes with a contract:
1 2 3 4 5 6
// even_int_t is an int that can only ever contain even values. typedef fhtagn::restricted<int, fhtagn::restrictions::numeric::even<int> > even_int_t; void foo(even_int_t const & param);
The beauty of this is that the
even constraint is evaluated before
foo()‘s function body is entered.
You’ll note that the restriction we’re using is a template argument to the restricted type. You can even chain restrictions, like this:
1 2 3 4 5 6 7
// positive_even_int_t is an int that can only ever contain positive // even values. typedef fhtagn::restricted<int, fhtagn::restrictions::numeric::positive<int, fhtagn::restrictions::numeric::even<int> > > positive_even_int_t;
Here, it’s first assured that the value to be assigned to the restricted data type is positive, then it’s assured it’s even. If either of the restrictions is violated, an exception is thrown, and nested restrictions are not evaluated any more1.
And that’s the gist of how restricted data types work. So how do the two implementations differ?
- It therefore makes sense to first use
positive, as that’s very easily evaluated and already excludes half of the search space before
evenneeds to be evaluated. Granted, the latter also excludes half of the search space, but at the cost of an additional division. Yes, I’m being picky here [↩]
Pages: 1 2