|
Boost : |
Subject: Re: [boost] [guidelines] why template errors suck
From: Eric Niebler (eric_at_[hidden])
Date: 2010-09-27 10:11:12
On 9/27/2010 12:49 AM, David Abrahams wrote:
> At Sun, 26 Sep 2010 22:31:54 -0400,
> Eric Niebler wrote:
>> On 9/26/2010 9:44 PM, David Abrahams wrote:
>>> On Sep 26, 2010, at 8:55 AM, Eric Niebler wrote:
>>>> On 9/25/2010 1:24 PM, David Abrahams wrote:
>>>>> On Sep 24, 2010, at 11:51 PM, Eric Niebler wrote:
>>>>>> On 9/24/2010 9:37 PM, David Abrahams wrote:
>>>>>>
>>>>>> Haha! No, not at all. Let's rephrase the problem a bit. If we still had
>>>>>> C++0x concepts, what would the concept SpiritParser look like, such that
>>>>>> we could define spirit::qi::rule::operator= such that it required its
>>>>>> RHS to satisfy the SpiritParser concept?
>>>>>
>>>>> That's easy to answer; just look at the operations that
>>>>> operator= et. al expect of such a type. Wouldn't SpiritParser
>>>>> just be some simple refinement of Callable?
>>>>
>>>> No. rule::operator= expects SpiritParser to be a strongly-typed tree.
>>>
>>> Meaning? Spell it out and you have your requirements.
>>
>> Meaning:
>>
>> + If the topmost node has tag-type "plus", there must be exactly one
>> child node that models SpiritParser
>> + If the topmost node has tag-type "shift_right", there must be exactly
>> two child nodes that model SpiritParser,
>> + If the topmost node has tag-type "subscript", there must be a left
>> node that models SpiritParser and a right node that models PhoenixLambda,
>> ...
>> etc, etc, etc, ad nauseum
>
> No offense, but did you really answer the question I asked? Does
> operator= actually use those requirements?
It does. operator= doesn't know how to process the tree (that is, what
the requirements are) until it looks at the top-most node type and
dispatches to the correct helper functions. Those functions have their
own requirements determined solely by the substructure of the trees they
operate on.
For instance, take semantic actions, denoted by the subscript tag. If a
subscript node appears anywhere in the tree, the right child of that
node must satisfy the concept PolymorphicFunctionObject. rule::operator=
will fail to compile if it does not; it has assumed that requirement as
a result of the recursive function calls made within the body of
operator=. I'd like to be able to check for that condition up front. I
still don't know how using concepts.
> On the face of it, it just
> seems a lot more likely that it simply requires its RHS to also be a
> SpiritParser.
Where a SpiritParser is ...?
>> How do I express that as a concept?
>
> Summoning up my dim memory of proposed concept notation (so there are
> guaranteed nits to pick), that might translate into something like:
>
> concept SpiritNode<typename Node, typename Tag>
> {
> }
>
> template <class Node>
> concept_map SpiritNode<typename Node, plus>
> {
> requires SameType<Node::children,int_<1> >;
> typename child_t;
> requires SpiritParser<child_t>;
> child_t child;
> }
>
> template <class Node>
> concept_map SpiritNode<typename Node, shift_right>
> {
> requires SameType<Node::children,int_<2> >;
> typename child1_t;
> requires SpiritParser<child1_t>;
> typename child2_t;
> requires SpiritParser<child2_t>;
>
> child1_t child1;
> child2_t child2;
> }
>
> template <class Node>
> concept_map SpiritNode<typename Node, subscript>
> {
> requires SameType<Node::children,int_<2> >;
> typename child1_t;
> requires SpiritParser<child1_t>;
> typename child2_t;
> requires PhoenixLambda<child2_t>;
>
> child1_t child1;
> child2_t child2;
> }
>
> concept RHSOfAssign<typename X>
> {
> typename tag_type; // Every RHSOfAssign has an associated tag_type
> requires SpiritNode<X, tag_type>;
> }
>
> This isn't really how concepts were "meant to be used," though.
You haven't shown how the SpiritNode and SpiritParser concepts are
related. There must be some recursive relationship, like "a SpiritParser
is a SpiritNode<plus> /or/ a SpiritNode<right_shift> /or/ ..." It
requires OR constraints which, as Sebastian has pointed out, were yanked
from the concepts proposal.
rule::operator= is an algorithm. The structure of the type on which it's
parametrized and the grammar to which that type must conform together
determine what the overall algorithm requirements are. It by necessity
cannot be expressed without OR constraints. What I seem to have is a
situation where an algorithm has type requirements that cannot be
expressed with concepts, so concepts cannot help me validate my type
parameter.
-- 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