まず、Boost VariantまたはUtreeのいずれかを使用する方がはるかに簡単な場合は、それらを使用して解決し、別のトピックでそれらの問題を解決しようとします。しかし、私は以下のようなツリーを構築できるようにしたいと思っています。
背景、問題に直接進みたい場合は無視してください。次のようなものを解析する式ツリーを構築できるようにしたいと思います。
"({a} == 0) && ({b} > 5)"
または標準的な数学式
"(2 * a) + b"
次に、ツリーを評価する前に、aとbを定義します。次のようになります。
a = 10;
double val = myExpression->Evaluate();
私の問題は、文字列を解析して式ツリーに組み込む試みを構築しようとしたときに発生します。抽象クラス「Expression」を使用して、「Variable」、「Constant」、「Binary」の式を派生させています(単項も実行しますが、問題には影響しません。ルールを使用してツリーに追加する際に問題が発生し続けます。 、だから私は明らかに何か間違ったことをしている。私は属性の周りに頭を包むのに苦労している。
私のツリーは次のとおりです(Tree.h):
class BinaryExpression;
typedef double (*func)(double, double);
class Expression
{
public:
    virtual double Evaluate() = 0;
};
class BinaryExpression : public Expression
{
private:
    Expression* lhs;
    Expression* rhs;
    func method;
    double Evaluate();
public:
    BinaryExpression(void);
    BinaryExpression(char op, Expression* lhs, Expression* rhs);
    BinaryExpression(char op);
    void operator()(Expression* lhs, Expression* rhs);
};
class ConstantExpression : public Expression
{
private:
    double value;
public:
    ConstantExpression(void);
    ConstantExpression(char op);
    ConstantExpression(double val);
    double Evaluate();
};
// Require as many types as there are fields in expression?
static double a;
static double b;
class VariableExpression : public Expression
{
private:
    char op;
public:
    VariableExpression(char op);
    double Evaluate();
};
BOOST_FUSION_ADAPT_STRUCT(
    BinaryExpression,
    (Expression*, lhs)
    (Expression*, rhs)
    (func, method)
)
BOOST_FUSION_ADAPT_STRUCT(
    VariableExpression,
    (char, op)
)
BOOST_FUSION_ADAPT_STRUCT(
    ConstantExpression,
    (double, op)
)
Tree.cpp
typedef double (*func)(double, double);
/////////////////////////////////////////////////////////////////////////////
// BINARY EXPRESSION
////////////////////////////////////////////////////////////////////////////
BinaryExpression::BinaryExpression(void) {}
BinaryExpression::BinaryExpression(char op, Expression* lhs, Expression* rhs)
{
    this->lhs = lhs;
    this->rhs = rhs;
    // Example, methods are held in another header
    if (op == '+')
        method = Add;
    else if (op == '-')
        method = Subtract;
}
double BinaryExpression::Evaluate()
{
    return method(lhs->Evaluate(), rhs->Evaluate());
}
BinaryExpression::BinaryExpression(char op)
{
    if (op == '+')
        method = Add;
    else if (op == '-')
        method = Subtract;
}
void BinaryExpression::operator()(Expression* lhs, Expression* rhs)
{
    this->lhs = lhs;
    this->rhs = rhs;
}
/////////////////////////////////////////////////////////////////////////////
// CONSTANT EXPRESSION
////////////////////////////////////////////////////////////////////////////
ConstantExpression::ConstantExpression() {}
ConstantExpression::ConstantExpression(char op)
{
    this->value = op - 48;
}
ConstantExpression::ConstantExpression(double val)
{
    value = val;
}
double ConstantExpression::Evaluate()
{
    return value;
}
/////////////////////////////////////////////////////////////////////////////
// VARIABLE EXPRESSION
////////////////////////////////////////////////////////////////////////////
VariableExpression::VariableExpression(char op)
{
    this->op = op;
}
double VariableExpression::Evaluate()
{
    // a and b are defined in the header, and are used to fill in the variables we     want to evaluate
    if (op == 'a')
        return a;
    if (op == 'b')
        return b;
    return 0;
}
今、私が手動でツリーを構築する場合、それはすべてうまく機能するので、それが構造化される方法に問題があるとは思わない。
これがGrammar.hです(さまざまなことを試したところからたくさんのコメントがあり、それらを削除することもできますが、試したこと/どこに行きたいかを示す価値があるかもしれません)
#include "Tree.h"
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_function.hpp>
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
qi::_1_type _1;
qi::_2_type _2;
// Pass functions to boost
boost::phoenix::function<BinaryExpression> plus = BinaryExpression('+');
boost::phoenix::function<BinaryExpression> minus = BinaryExpression('-');
template <typename Iterator>
struct ExpressionParser : qi::grammar<Iterator, BinaryExpression(), ascii::space_type>
{
    ExpressionParser() : ExpressionParser::base_type(expression)
    {
        qi::_3_type _3;
        qi::_4_type _4;
        qi::char_type char_;
        qi::uint_type uint_;
        qi::_val_type _val;
        qi::raw_type raw;
        qi::lexeme_type lexeme;
        qi::alpha_type alpha;
        qi::alnum_type alnum;
        qi::bool_type bool_;
        qi::double_type double_;
        expression = //?
            additive_expr                       [_val = _1]
            ;
        //equality_expr = 
        //      relational_expr >> 
        //      *(lit("==") > relational_expr)      [/*Semantice action to add to tree*/]
        //      ;
        additive_expr =
            primary_expr >>
            ( '+' > primary_expr)               [plus(_val, _1)]   
            | ( '-' > primary_expr)             [minus(_val, _1)]
            ;
        // Also tried "_val = plus(_1, _2)"
        primary_expr =
            constant                                [_val = _1]
            | variable                          [_val = _1]
            //| '(' > expression > ')'          [_val = _1]
            ;
        string %=
            '{' >> *(char_ - '}') >> '}'
            ;
        // Returns ConstantExpression
        constant =
            double_                                 [_val = _1];
        // Returns VariableExpression
        variable =
            char_                                   [_val = _1]
            ;
    }
    // constant expression = double
    // variable expression = string
    qi::rule<Iterator, BinaryExpression(), ascii::space_type>
        expression;
    qi::rule<Iterator, BinaryExpression(), ascii::space_type>
        // eventually will deal with all these rules
        equality_expr,
        relational_expr,        
        logical_expr,
        additive_expr,
        multiplicative_expr,
        primary_expr
            ;
    qi::rule<Iterator, ConstantExpression(), ascii::space_type>
        constant
        ;
    qi::rule<Iterator, VariableExpression(), ascii::space_type>
        variable
        ;
    qi::rule<Iterator, std::string(), ascii::space_type>
        string
        ;
};
ですから、これは本当にハッキングされていますが、うまくいけば、私が達成しようとしていることを示すでしょう。アドバイスやヒントをいただければ幸いです。誰かがバリアントやutreeを使用せずにこのようなツリーを構築した例はありますか?
また、慣例が破られた場合は申し訳ありませんが、私のフォーマットでは、できるだけ読みやすくするようにしました。