
Hi,
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 possible. Below is an excerpt from the motivation section of the documentation. Best regards, Robert =================== 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.