Boost logo

Boost :

From: Robert Kawulak (kawulak_at_[hidden])
Date: 2006-04-26 16:21:44


> From: Spencer Collyer

> bounds:
> This determines what the bounds on the sparse_array are, and
> how values
> that exceed them are handled. For example, the 'unbounded'
> policy allows
> virtually any positive value of the subscript type to be
> used, 'bounded'
> only allows values within the (compile-time specified) max
value and
> throws if a subscript exceeding this is given, while
> 'clamped' makes such
> value equal to the max value.

I'm working (actually, I'm having a long pause with the work :P)
on a Boost library that will actually implement this piece of
functionality, i.e. constrained types. In short, it aims to
provide a set of flexible, policy-based template classes allowing
to create constrained types, like bounded types with compile-type
bounds, run-time specified bounds etc. The code is almost ready,
but the documentation and tests need work.

If you'd be interested in reusing my library in your project,
just let me know. Unfortunately I can't tell when the library
would be 100% ready, although I try to finish it as soon as

Below is an excerpt from the motivation section of the

Best regards,


The Boost Constrained Types library contains class templates
useful for creating constrained types. The simplest example of a
constrained type is hour. The only valid values for an hour
within a day are integers from the range [0, 23]. Unfortunately
there's no C++ type which exactly matches this set of valid
values, so a larger integral type (e.g. int) must be used to
represent hours. But this can lead to errors -- for instance, a
programmer may accidentally assign an invalid value, say 26, to a
variable holding an hour. The Boost Constrained Types library
provides a mechanism protecting against such mistakes:

bounded_int<int, 0, 23>::type hour;
hour = 20; // OK
hour = 26; // error -- throws an exception

Another feature of the library is the ability to specify what
happens in case of assignment of an invalid value. For instance,
an exception may be thrown as in the example above, or the value
may be adjusted to meet the constraint criterions:

wrapping_int<int, 0, 255>::type buffer_index;
buffer_index = 257; // OK -- adjusts the value to fit in the
range by wrapping it
assert(buffer_index == 1);

The library doesn't focus only on constrained types that hold a
value belonging to a specified range (i.e., bounded types).
Virtually any constraint can be imposed by defining an
appropriate predicate:

// A constraint predicate
struct is_odd {
  bool operator () (int i) const
    { return (i % 2) != 0; }

// And the usage is as simple as:
constrained<int, is_odd>::type odd_int(1);
odd_int = 11; // OK
odd_int++; // error -- throws an exception

The library is designed to give as much flexibility as possible
in defining constraints and behavior in cases when they are
crossed, yet to be efficient and allow compilers to apply their
optimizations. It uses policies to customize behavior and allows
users to supply their custom policy classes. A user has a lot of
freedom: a bounded type, like hours or buffer_index above, may
have bounds which are defined at compile-time and do not occupy
space at all, or bounds that can be adjusted at runtime. Or one
compile-time bound and the other adjustable. The behavior in case
of crossing the bounds may also differ for each of the bounds --
e.g. an exception may be thrown if the assigned value is too
small, but it may be clipped to the upper bound if it is too big.

Note that this library doesn't provide a protection against
integer operations overflows -- it's simply not its task. For
more discussion on this and other issues see the rationale.

Boost list run by bdawes at, gregod at, cpdaniel at, john at