Boost logo

Boost :

From: Chad Parry (spam_at_[hidden])
Date: 2006-08-17 18:55:47


I would like to know if many people in the community think the following
library would be useful.

I would like to define concepts using this syntax:

        template<typename left_type, typename right_type = left_type>
        struct less_than_comparable
        {
            static var<left_type const> left;
            static var<right_type const> right;
            static var<bool> b;
            typedef CONCEPTS_USE_PATTERN(b = (left < right)) constraints;
        };

In the code above the less_than_comparable<T, U> concept is defined. The
var<> type is meant to resemble the Var<> in Stroustrup's concept proposals.
The CONCEPTS_USE_PATTERN(EXP) macro expands to BOOST_TYPEOF(EXP). The b,
left and right variables have lambda-like capabilities where you can apply
any operation on them and they return a complex type that remembers what
operations have been applied.

Functions that want to enforce concepts would use this syntax:

        template<typename operand_type>
        bool my_less_than(operand_type left, operand_type right)
        {
            // Enforce the model.
            typedef less_than_comparable<operand_type> model;
            BOOST_STATIC_ASSERT(is_match<model>::value);
            constrained_proxy<1, model> constrained_left(constrain<1,
model>(left));
            constrained_proxy<2, model> constrained_right(constrain<2,
model>(right));
            // Use the constrained proxies just like regular types.
            return (constrained_left < constrained_right);
        }

Obviously this syntax is more cumbersome than the current Boost Concept
Check Library's. But it offers more power too:

1) The author doesn't have to hand-craft an archetype class! The model
knows what operations should be allowed and the constrained_proxy<> class
enforces that only those operations are taken.

2) It is possible to check whether a model is valid without causing a fatal
error. That's what the is_match<model> metapredicate is for. This could be
used to dispatch different optimized code depending on which concepts the
type is known to model. Now, there are some things that can't be detected
by library code (like the presence of a default constructor) so I would have
to rely on authors to provide hints about those. I'm planning on just
assuming that any requirements I can't detect are fulfilled, and then the
compiler will complain if that's wrong.

3) The concepts can be built up from primitives using and_ and or_ and not_
operations, just like in Stroustrup's proposals. For example, the concept
above could have included this statement instead: "typedef
and_<CONCEPTS_USE_PATTERN(b = left < right), CONCEPTS_USE_PATTERN(b = right
< left), copy_constructible<left> > constraints;"

4) This use pattern syntax more closely resembles the C++0x use pattern
proposals than any other existing library.

5) The constrained_proxy class prevents certain errors where a pathological
type behaves unexpectedly. I'm talking about functions like
"evil_bool_proxy operator<(mytype, mytype)" where evil_bool_proxy defines
its own && and || operators. In the expression, "(a < b) && (c < d)" the
constrained_proxy enforces that the && operation gets applied to bool
values, not to evil_bool_proxy values.

6) This mechanism allows you to express that a model has important semantic
implications also. The library assumes that a model is valid if it is a
structural match. But you can override that by saying, "template<typename
value_type> declare_match<forward_iterator<istream_iterator<value_type> > >
: false_ { };"

7) Traits classes could potentially be added to this library so that authors
could express mappings such as that the constrained_proxy should call a free
function "push_back(my_seq, elem)" instead of the normal "my_seq.push_back
(elem)" for a given sequence type.

So far I have gotten var<> and declare_match<> and is_match<> to compile.
I've also finished and_<>, or_<> and not_<>. I'm working on
constrained_proxy<>.

-- chad


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk