Boost logo

Boost :

Subject: Re: [boost] [guidelines] why template errors suck
From: David Abrahams (dave_at_[hidden])
Date: 2010-09-27 15:01:43


At Mon, 27 Sep 2010 13:53:22 -0400,
Eric Niebler wrote:
>
> On 9/27/2010 1:02 PM, David Abrahams wrote:
> > 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:
> >>>>>> 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
> <snip>
> >>>> 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.
>
> You were the one who invented the SpiritNode concept, and then didn't
> tie it into the discussion!

Oh, whoops. Replace RHSOfAssign with SpiritParser.

> I described a recursive description of the
> SpiritParser concept and you showed one without any recursive property
> at all. :-P

Uhm, still not sure where the recursion is in your description.

> >> There must be some recursive relationship, like "a SpiritParser
> >> is a SpiritNode<plus> /or/ a SpiritNode<right_shift> /or/ ..."

And that's not recursion.

> > 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> >
> > {
> > // ...
> > }
>
> Not according to my reading of the standard. A concept_map is for
> mapping *types* to concepts, not *concepts* to concepts, as you appear
> to be doing here.

Sorry, I may have spelled it wrong, but you can do it. Concept map
templates allow you to map types that satisfy given concepts to other
concepts. There's an example on page 44 of
http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2008/n2710.pdf

  template <typename Node>
    requires SpiritNode<Node, plus>
  concept_map SpiritParser<Node>
  {
      // ...
  }

  template <typename Node>
    requires SpiritNode<Node, right_shift>
  concept_map SpiritParser<Node>
  {
      // ...
  }

> I can also find no examples in the standard of using concept maps to map
> one concept to another. Can you?
>
> >> which, as Sebastian has pointed out, were yanked
> >> from the concepts proposal.
> >
> > With good reason.
>
> Algorithmic complexity, IIRC.

Also there's no real-world scenario that can benefit from it. There's
nothing that OR constraints could express that couldn't also be
expressed with concept_maps, and once you got inside the constrained
template you wouldn't be able to use any operations that aren't in the
intersection of the constraints (remember that template bodies need to
typecheck against their constraints).

-- 
Dave Abrahams
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