Boost logo

Boost :

Subject: Re: [boost] [guidelines] why template errors suck
From: Eric Niebler (eric_at_[hidden])
Date: 2010-09-27 14:05:55


On 9/27/2010 1:16 PM, Smith, Jacob N wrote:
>
> Disclaimer: it has been a couple of years since I worked with concepts.
>
> concept ProtoNode<typename Node>
> {
> ChildList children = Node::children;
> }
>
> // Assert the pseudoproto-unary_plus models a ProtoNode
> template <ProtoNode Node> concept_map ProtoNode< unary_plus<Node> > { }
>
> // Assert the pseudoproto-binary_plus models a ProtoNode
> template <ProtoNode LNode, ProtoNode RNode> concept_map ProtoNode< binary_plus<LNode, RNode> > { }
>
> // Assert the pseudoproto-binary_minus models a ProtoNode
> template <ProtoNode LNode, ProtoNode RNode> concept_map ProtoNode< binary_minus<LNode, RNode> > { }
>
> struct foo { };
> struct bar { };
> struct baz { };
>
> concept_map ProtoNode<foo> { typedef nil children; }
> concept_map ProtoNode<bar> { typedef nil children; }
>
> auto rule = foo() + (+ bar()) + baz();
>
> // error: baz does not satisfy the concept "ProtoNode".

Yes, you can concept-check a tree that need not conform to a grammar.

> // Pseudo-spirit concept.
> concept SpiritNode<typename Node>
> {
> ChildList children = Node::children;
> ForwardIterator iterator = Node::iterator;
>
> iterator parse (iterator, iterator, Node&);
> }
>
> // Assert that all SpiritNodes model ProtoNodes
> template <SpiritNode Node> concept_map ProtoNode<Node> { }
>
> concept ShortProtoTree<typename Node>
> {
> // Checks that we have (in "hand-wavey" english):
> // ProtoNode node that contains two ProtoNode nodes of ProtoNode.
> // My personal ConceptGCC build uses "," not "&&".
> requires ProtoNode<Node>,
> ProtoNode<get_child<_0, ProtoNode<Node>::children>::type>,
> ProtoNode<get_child<_1, ProtoNode<Node>::children>::type>;
> }
>
> concept IsBinaryPlusOperator<typename Node> { requires SpiritNode<Node>; }
> concept IsUnaryPlusOperator<typename Node> { requires SpiritNode<Node>; }
>
> concept SpiritPlusesShortProtoTree<typename Node>
> {
> // Checks that the "ShortProtoTree" is the expression: (+X) + (+Y)
> requires SpiritNode<Node>,
> ShortProtoTree<Node>,
> IsBinaryPlusOperator<Node>,
> IsUnaryPlusOperator<get_child<_0, ProtoNode<Node>::children>::type>,
> IsUnaryPlusOperator<get_child<_1, ProtoNode<Node>::children>::type>;
> }
>
> I am waving my hands at the "get_child" functor; it is straightforward to describe using concepts.
>
> Concepts are fairly tightly related to algebra declarations. Any algebra can be thought of as a tree, therefore, any tree should be checkable via concepts. Disjoint ("or") concept requirements are not needed in this situation since the concept mechanism will choose the most specialized concept that the model satisfies, not the least specialized. [This is not to say that disjoint concepts aren't necessary in some cases.]

You have shown that you can concept-check the expression (+X) + (+Y).
You did it by traversing the tree in the SpiritPlusesShortProtoTree
concept and verifying each node explicitly. I don't see (yet) how you
can generalize this.

You appear to be writing a new concept for each valid tree type. But
there are an infinite number of trees that are valid Spirit trees (and
an infinite number that are not). I still don't see how concepts can
tell the difference between the two sets.

-- 
Eric Niebler
BoostPro Computing
http://www.boostpro.com

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