BOOST_SPIRIT_DEBUG_NODE无法在变体节点上编译

BOOST_SPIRIT_DEBUG_NODE fails to compile on variant node

本文关键字:节点 编译 SPIRIT DEBUG NODE BOOST      更新时间:2023-10-16

以下代码不编译BOOST_SPIRIT_DEBUG_NODE( 表达式),其中表达式是变体节点(不过,我不是 100% 某些变体节点与它有任何关系)。

如果我注释掉这一行,一切似乎都运行良好。

对编译错误进行眼球解析,我看到:

/usr/local/include/boost/spirit/home/support/attributes.hpp:1203:13: error: cannot bind ‘std::basic_ostream<char>’ lvalue to ‘std::basic_ostream<char>&&’

如果这还不足以告诉我们错误的原因,请编译下面的代码,以获取详细的编译转储。

请注意,代码与文档中的示例 95% 相同。

我只是在变体类型中添加了一个std::string,并尝试添加永远有用的 BOOST_SPIRIT_DEBUG_NODE(),以便我可以看到发生了什么。

#define BOOST_SPIRIT_DEBUG
#include <boost/spirit/include/qi.hpp>
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>
#include <boost/spirit/include/classic_symbols.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/io.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/regex.hpp>   // std::regex not fully implemented in stdc++ yet
#include <string>
#include <map>
#include <utility>
#include <functional>
#include <iostream>
#include <string>
#include <vector>
namespace client
{
    namespace qi = boost::spirit::qi;
    namespace ascii = boost::spirit::ascii;
    struct binary_op;
    struct unary_op;
    struct nil {};
    struct expression_ast
    {
        typedef
        boost::variant<
        nil // can't happen!
        , double
        , std::string
        , boost::recursive_wrapper<expression_ast>
        , boost::recursive_wrapper<binary_op>
        , boost::recursive_wrapper<unary_op>
        >
        type;
        expression_ast()
            : m_expr(nil()) {}
        template <typename Expr>
        expression_ast(Expr const& expr)
            : m_expr(expr) {}
        expression_ast& operator+=(expression_ast const& rhs);
        expression_ast& operator-=(expression_ast const& rhs);
        expression_ast& operator*=(expression_ast const& rhs);
        expression_ast& operator/=(expression_ast const& rhs);
        type m_expr;
    };
    struct binary_op
    {
        binary_op(
            char op
            , expression_ast const& left
            , expression_ast const& right)
            : m_op(op), m_left(left), m_right(right) {}
        char m_op;
        expression_ast m_left;
        expression_ast m_right;
    };
    struct unary_op
    {
        unary_op(
            char op
            , expression_ast const& subject)
            : m_op(op), m_subject(subject) {}
        char m_op;
        expression_ast m_subject;
    };
    expression_ast& expression_ast::operator+=(expression_ast const& rhs)
    {
        m_expr = binary_op('+', m_expr, rhs);
        return *this;
    }
    expression_ast& expression_ast::operator-=(expression_ast const& rhs)
    {
        m_expr = binary_op('-', m_expr, rhs);
        return *this;
    }
    expression_ast& expression_ast::operator*=(expression_ast const& rhs)
    {
        m_expr = binary_op('*', m_expr, rhs);
        return *this;
    }
    expression_ast& expression_ast::operator/=(expression_ast const& rhs)
    {
        m_expr = binary_op('/', m_expr, rhs);
        return *this;
    }
    // We should be using expression_ast::operator-. There's a bug
    // in phoenix type deduction mechanism that prevents us from
    // doing so. Phoenix will be switching to BOOST_TYPEOF. In the
    // meantime, we will use a phoenix::function below:
    struct negate_expr
    {
        template <typename T>
        struct result
        {
            typedef T type;
        };
        expression_ast operator()(expression_ast const& expr) const
        {
            return expression_ast(unary_op('-', expr));
        }
    };
    static boost::phoenix::function<negate_expr> neg;
    struct ast_print
    {
        typedef std::string result_type;
        std::string operator()(qi::info::nil) const
        {
            return "";
        }
        std::string operator()(std::string const& str) const
        {
            return str;
        }
        std::string operator()(double d) const
        {
            std::ostringstream oss;
            oss << d;
            return oss.str();
        }
        std::string operator()(expression_ast const& ast) const
        {
            return boost::apply_visitor(*this, ast.m_expr);
        }
        std::string operator()(binary_op const& expr) const
        {
            std::ostringstream oss;
            oss << "op:" << expr.m_op << "(";
            oss << boost::apply_visitor(*this, expr.m_left.m_expr);
            oss << ", ";
            oss << boost::apply_visitor(*this, expr.m_right.m_expr);
            oss << ')';
            return oss.str();
        }
        std::string operator()(unary_op const& expr) const
        {
            std::ostringstream oss;
            oss << "op:" << expr.m_op << "(";
            oss << boost::apply_visitor(*this, expr.m_subject.m_expr);
            oss << ')';
            return oss.str();
        }
    };
    template <typename Iterator>
    struct ParserGenerator : qi::grammar<Iterator, expression_ast(), ascii::space_type>
    {
        ParserGenerator() : ParserGenerator::base_type(expression)
    {
        using qi::_val;
        using qi::_1;
        using qi::double_;
        using qi::iso8859_1::char_;
        using qi::iso8859_1::space;
        using qi::eol;
        comment =
            space >> ("//" >> *(char_ - eol) >> eol)
            ;
        expression =
            term                            [_val = _1]
            >> *(   ('+' >> term            [_val += _1])
                |   ('-' >> term            [_val -= _1])
                )
            ;
        term =
            factor                          [_val = _1]
            >> *(   ('*' >> factor          [_val *= _1])
                |   ('/' >> factor          [_val /= _1])
                )
            ;
        factor =
              symbol                        [_val = _1]
            | double_                       [_val = _1]
            |   '(' >> expression           [_val = _1] >> ')'
            |   ('-' >> factor              [_val = neg(_1)])
            |   ('+' >> factor              [_val = _1])
            ;
        symbol %= boost::spirit::lexeme[ +(qi::char_ - qi::char_("()-+*/")) ]
            ;
        BOOST_SPIRIT_DEBUG_NODE(expression);     // <--- TROUBLE COMPILING THIS LINE
        BOOST_SPIRIT_DEBUG_NODE(symbol);
    }
    qi::rule<Iterator, expression_ast(), ascii::space_type>
        expression, term, factor, comment;
    qi::rule<Iterator, std::string(), ascii::space_type>
        symbol;
    };
}
int main(int argc, char* argv[])
{
    using boost::spirit::ascii::space;
    using client::expression_ast;
    using client::ast_print;
    typedef std::string::const_iterator iterator_type;
    typedef client::ParserGenerator<iterator_type> ParserGenerator;
    ParserGenerator pg;   // our grammar
    std::string predicate( "i_.c+x[0]" );
    expression_ast  ast;
    ast_print       printer;
    iterator_type iter = predicate.begin(), end = predicate.end();
    if ( phrase_parse( iter, end, pg, space, ast ))
    {
        std::cerr << printer( ast ) << std::endl;
    }
    return 0;
}

错误在这里

初始化 «std::basic_ostream<_CharT, _Traits>& 的参数 1 std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [_CharT = 字符,_Traits = std::char_traits,_Tp = 客户端::expression_ast]»

您的expression_ast没有operator <<过载。

std::ostream& operator << (std::ostream& stream, const expression_ast& expr)
{
   ast_print printer;
   stream << printer(expr) << std::endl;
   return stream;
}

用这个简单的补充为我编译。