I have a boost::spirit
parser that is supposed to simply assign a pointer to its attribute:
rule<CompoundExpression *(Scope &)> var_ref = var<CompoundExpression>()(_r1) [
_val = new_<Reference<Variable<CompoundExpression>>>(_1)
];
where var<CompoundExpression>()
is a just function that returns a reference to a static rule that does the actual parsing. I use the same assignment action with other instantiations of the Reference<Variable<T>>
template all over the code and it's fine, except for the one that uses the CompoundExpression
parameter.
The literal GCC error is this:
In file included from /usr/include/boost/phoenix/core/actor.hpp:20,
from /usr/include/boost/phoenix/core.hpp:12,
from /usr/include/boost/spirit/include/phoenix_core.hpp:11,
from /usr/include/boost/spirit/home/support/argument.hpp:18,
from /usr/include/boost/spirit/home/qi/nonterminal/rule.hpp:29,
from /usr/include/boost/spirit/home/qi/nonterminal.hpp:14,
from /usr/include/boost/spirit/include/qi_nonterminal.hpp:16,
from /home/ich/sync/ConTrAkt/gologpp/src/parser/utilities.h:7,
from /home/ich/sync/ConTrAkt/gologpp/src/parser/compound_expression.h:4,
from /home/ich/sync/ConTrAkt/gologpp/src/parser/compound_expression.cpp:1:
/usr/include/boost/phoenix/core/is_nullary.hpp: In instantiation of ‘struct boost::phoenix::result_of::is_nullary<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::assign, boost::proto::argsns_::list2<boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::attribute<0> >, 0>, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::phoenix::tag::new_, boost::proto::argsns_::list2<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::phoenix::detail::target<gologpp::Reference<gologpp::Variable<gologpp::TypedExpression<gologpp::CompoundType> > > > >, 0>, boost::phoenix::actor<boost::spirit::argument<0> > >, 2> > >, 2>, void>’:
/usr/include/boost/phoenix/core/actor.hpp:178:13: required from ‘struct boost::phoenix::result_of::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::assign, boost::proto::argsns_::list2<boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::attribute<0> >, 0>, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::phoenix::tag::new_, boost::proto::argsns_::list2<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::phoenix::detail::target<gologpp::Reference<gologpp::Variable<gologpp::TypedExpression<gologpp::CompoundType> > > > >, 0>, boost::phoenix::actor<boost::spirit::argument<0> > >, 2> > >, 2> >’
/usr/include/boost/phoenix/core/actor.hpp:271:9: required from ‘struct boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::assign, boost::proto::argsns_::list2<boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::attribute<0> >, 0>, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::phoenix::tag::new_, boost::proto::argsns_::list2<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::phoenix::detail::target<gologpp::Reference<gologpp::Variable<gologpp::TypedExpression<gologpp::CompoundType> > > > >, 0>, boost::phoenix::actor<boost::spirit::argument<0> > >, 2> > >, 2> >’
/home/ich/sync/ConTrAkt/gologpp/src/parser/compound_expression.cpp:22:58: required from here
/usr/include/boost/phoenix/core/is_nullary.hpp:115:16: error: base type ‘boost::phoenix::evaluator::impl<const boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::assign, boost::proto::argsns_::list2<boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::attribute<0> >, 0>, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::phoenix::tag::new_, boost::proto::argsns_::list2<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::phoenix::detail::target<gologpp::Reference<gologpp::Variable<gologpp::TypedExpression<gologpp::CompoundType> > > > >, 0>, boost::phoenix::actor<boost::spirit::argument<0> > >, 2> > >, 2>&, boost::phoenix::vector2<mpl_::bool_<true>, boost::phoenix::is_nullary>, boost::proto::envns_::empty_env>::result_type’ {aka ‘const boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::assign, boost::proto::argsns_::list2<boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::attribute<0> >, 0>, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::phoenix::tag::new_, boost::proto::argsns_::list2<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::phoenix::detail::target<gologpp::Reference<gologpp::Variable<gologpp::TypedExpression<gologpp::CompoundType> > > > >, 0>, boost::phoenix::actor<boost::spirit::argument<0> > >, 2> > >, 2>&’} fails to be a struct or class type
struct is_nullary
^~~~~~~~~~
Since that is virtually unreadable, I'll try to clang-format
it. So I guess it comes down to the last line:
/usr/include/boost/phoenix/core/is_nullary.hpp:115:16: error: base type
‘boost::phoenix::evaluator::impl<
const boost::proto::exprns_::basic_expr<
boost::proto::tagns_::tag::assign,
boost::proto::argsns_::list2<
boost::proto::exprns_::expr<
boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<boost::spirit::attribute<0>>, 0>,
boost::phoenix::actor<boost::proto::exprns_::basic_expr<
boost::phoenix::tag::new_,
boost::proto::argsns_::list2<
boost::proto::exprns_::basic_expr<
boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<
boost::phoenix::detail::target<gologpp::Reference<
gologpp::Variable<gologpp::TypedExpression<
gologpp::CompoundType>>>>>,
0>,
boost::phoenix::actor<boost::spirit::argument<0>>>,
2>>>,
2> &,
boost::phoenix::vector2<mpl_::bool_<true>, boost::phoenix::is_nullary>,
boost::proto::envns_::empty_env>::result_type’ {
aka ‘const boost::proto::exprns_::basic_expr<
boost::proto::tagns_::tag::assign,
boost::proto::argsns_::list2<
boost::proto::exprns_::expr<
boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<boost::spirit::attribute<0>>, 0>,
boost::phoenix::actor<boost::proto::exprns_::basic_expr<
boost::phoenix::tag::new_,
boost::proto::argsns_::list2<
boost::proto::exprns_::basic_expr<
boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<
boost::phoenix::detail::target<gologpp::Reference<
gologpp::Variable<gologpp::TypedExpression<
gologpp::CompoundType>>>>>,
0>,
boost::phoenix::actor<boost::spirit::argument<0>>>,
2>>>,
2> &’}
fails to be a struct or class type
Note that gologpp::TypedExpression<gologpp::CompoundType
is typedef'd as gologpp::CompoundExpression
Now if I'm reading that correctly, this base type of result_of::is_nullary
(/usr/include/boost/phoenix/core/is_nullary.hpp:115) somehow happens to be a reference type and that is the problem. My Reference<Variable<CompoundExpression>>
type seems perfectly fine, I can construct objects from it and otherwise use it as I'd expect.
Also the problem it seems is with the whole phoenix assignment expression, and not with its LHS or RHS.
Looking at boost/phoenix/core/is_nullary.hpp:115:
struct is_nullary
: boost::phoenix::evaluator::impl<
Expr const &
, vector2<
mpl::true_
, boost::phoenix::is_nullary
>
, proto::empty_env
>::result_type
{};
It seems to that somehow Expr const &
(which in my case is the assignment expression) is becoming the result_type
, which shouldn't happen. But then why does it and how could I be causing it?
OK, so it looks like I also need to
#include <boost/phoenix/object/dynamic_cast.hpp>
#include <boost/phoenix/operator/self.hpp>
for the polymorphic assignment to work. Something I didn't notice because it was indirectly included in other cases.