$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
Subject: Re: [boost] [guidelines] why template errors suck
From: David Abrahams (dave_at_[hidden])
Date: 2010-09-27 13:02:25
On Sep 27, 2010, at 10:11 AM, Eric Niebler wrote:
> 
> 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.
Of course not; you didn't say they were related.  I just translated the constraints you wrote down into concepts-land.
> There must be some recursive relationship, like "a SpiritParser
> is a SpiritNode<plus> /or/ a SpiritNode<right_shift> /or/ ..."  It
> requires OR constraints
Do say that, you just use concept_maps to declare that SpiritNode<plus> models SpiritParser, etc.:
  concept_map SpiritParser<SpiritNode<plus> >
  {
      // ...
  }
  concept_map SpiritParser<SpiritNode<right_shift> >
  {
      // ...
  }
> which, as Sebastian has pointed out, were yanked
> from the concepts proposal.
With good reason.
> 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.
I don't understand how you can come to that conclusion with such certainty, while at the same time declaring that you don't understand concepts.
> 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.
I don't see it (yet), sorry.  Am I missing something?
-- Dave Abrahams BoostPro Computing http://boostpro.com