|
Boost : |
Subject: Re: [boost] [parameter] type requirement compiler error
From: Daniel Wallin (daniel_at_[hidden])
Date: 2011-11-08 09:29:08
On Sun, Nov 6, 2011 at 8:12 PM, Lorenzo Caminiti <lorcaminiti_at_[hidden]> wrote:
On Sat, Nov 5, 2011 at 7:17 AM, Lorenzo Caminiti <lorcaminiti_at_[hidden]> wrote:
> > Please someone help :)
>
> I looked into Boost.Parameter tests and
> boost/libs/parameter/test/deduced_dependent_predicate.cpp uses
> tag::x::_ so I modified the example to the following that compiles:
>
[...]
>
> #include <boost/parameter.hpp>
> #include <boost/mpl/placeholders.hpp>
> #include <boost/type_traits/is_same.hpp>
> #include <boost/type_traits/add_pointer.hpp>
> #include <iostream>
>
> BOOST_PARAMETER_NAME(x)
> BOOST_PARAMETER_NAME(y)
>
> BOOST_PARAMETER_FUNCTION(
> (int),
> f,
> tag,
> (required
> (x, *)
> (y, *(boost::is_same<boost::mpl::_,
> boost::add_pointer<tag::x::_>::type>)) // (2)
^^^^^^
Here's the problem in this case: you are eagerly evaluating
add_pointer<>. Remove the ::type and this works:
(y, *(boost::is_same<boost::mpl::_,
boost::add_pointer<tag::x::_> >))
This is really the same problem that the documentation sample has:
(required (graph, *) )
(optional (root_vertex,
(typename boost::graph_traits<graph_type>::vertex_descriptor),
*boost::vertices(graph).first) )
graph_traits<..> is eagerly evaluated here, resulting in the error. You
need to be lazy here, but there's no appropriate metafunction in the
graph library, so we need to write one:
template <class G>
struct vertex_descriptor {
typedef typename boost::graph_traits<G>::vertex_descriptor type;
};
and then do:
(required (graph, *) )
(optional (root_vertex,
*(boost::is_convertible<mpl::_, vertex_descriptor<tag::graph::_> >),
*boost::vertices(graph).first) )
Note that you need can't use:
(vertex_descriptor<tag::graph::_>)
because the library doesn't properly treat the predicate as a
metafunction in all the places that it should.
> A far as I can tell, there are two major issues here that should be
> fixed in Boost.Parameter:
> 1) The docs don't mention tag::xyz::_ at all, they refer to xyx_type
> which only works within the function definition and not in the
> function declaration.
Yes, clearly a documentation bug.
> 2) The change from x_type to tag::xyz::_ broke the ability to
> manipulate the parameter type in the function declaration. For
> example, it broke the ability for Boost.Parameter to program the DFS
> interface. This seems a major feature that was lost and
> Boost.Parameter should be fixed to regain such a feature. BTW, why was
> x_type changed to tag::xyx::_? What's the benefit for that?
It wasn't changed actually, it always worked like this.
Predicates are invoked with two arguments: the argument type to
validate, and the partial argument pack containing the preceding
function parameters.
template <class Arg, class Pack>
struct predicate;
tag::x::_ is actually a shortcut for:
boost::parameter::value_type<tag::x, mpl::_2>
intended to simplify referring to preceding parameters in the
predicates.
Now, if we wanted the ability to access preceding parameter types like
in the docs, the macros would need to wrap the user predicates like
this:
template <class Arg, class Pack>
struct z_predicate {
typedef typename parameter::value_type<tag::x, Pack> x_type;
...
typedef typename parameter::value_type<tag::y, Pack> y_type;
typedef typename mpl::apply2<actual-predicate, Arg, Pack>::type type;
};
It wasn't done this way for compile time performance reasons. Perhaps we
could have done this in a simpler way, where we would build the entire
argument pack and then use one single predicate to validate the entire
thing once, but that's not how it currently works.
Looking at the current docs, it's full of problems like this. :( In
fact, *all* of the predicates in the DFS example are wrong.
Does this help?
-- Daniel Wallin 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