boost::spirit 属性赋值:struct is_nullary:基类型不能是结构或类类型

Vic*_*aré 2 c++ boost boost-spirit boost-phoenix

我有一个boost::spirit解析器,它应该简单地分配一个指向其属性的指针:

rule<CompoundExpression *(Scope &)> var_ref = var<CompoundExpression>()(_r1) [
    _val = new_<Reference<Variable<CompoundExpression>>>(_1)
];
Run Code Online (Sandbox Code Playgroud)

wherevar<CompoundExpression>()是一个 just 函数,它返回对执行实际解析的静态规则的引用。我Reference<Variable<T>>在整个代码中对模板的其他实例使用相同的赋值操作,这很好,除了使用CompoundExpression参数的那个。

字面 GCC 错误是这样的:

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
                ^~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)

由于这实际上是不可读的,我会尝试clang-format一下。所以我想它归结为最后一行:

/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
Run Code Online (Sandbox Code Playgroud)

请注意,gologpp::TypedExpression<gologpp::CompoundTypetypedef 为gologpp::CompoundExpression

现在,如果我没看错,这个result_of::is_nullary(/usr/include/boost/phoenix/core/is_nullary.hpp:115) 的基本类型在某种程度上恰好是一个引用类型,这就是问题所在。我的Reference<Variable<CompoundExpression>>类型看起来非常好,我可以从中构造对象,否则可以按照我的预期使用它。问题似乎还在于整个凤凰分配表达式,而不是它的 LHS 或 RHS。

查看 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
        {};
Run Code Online (Sandbox Code Playgroud)

似乎不知何故Expr const &(在我的情况下是赋值表达式)正在变成result_type,这不应该发生。但是为什么会这样,我怎么会导致它呢?

Vic*_*aré 6

好的,看来我也需要

#include <boost/phoenix/object/dynamic_cast.hpp>
#include <boost/phoenix/operator/self.hpp>
Run Code Online (Sandbox Code Playgroud)

使多态赋值起作用。我没有注意到的东西,因为它间接包含在其他情况下。