Is there any kind of “expression class” (C++)

前端 未结 9 1409
眼角桃花
眼角桃花 2020-12-13 14:45

I am creating a game that lets the player enter input, changes some states, then checks if a \"goal value\" is true (obviously this description is muchly simplified), and I

相关标签:
9条回答
  • 2020-12-13 15:24

    Dynamic expressions

    If you want to receive a string from the user and built an expression from that, maybe the C++ Mathematical Expression Library fits your bill?

    template<typename T>
    void trig_function()
    {
       std::string expression_string = "clamp(-1.0,sin(2 * pi * x) + cos(x / 2 * pi),+1.0)";
       T x;
       exprtk::symbol_table<T> symbol_table;
       symbol_table.add_variable("x",x);
       symbol_table.add_constants();
    
       exprtk::expression<T> expression;
       expression.register_symbol_table(symbol_table);
    
       exprtk::parser<T> parser;
       parser.compile(expression_string,expression);
    
       for (x = T(-5.0); x <= T(+5.0); x += 0.001)
       {
          T y = expression.value();
          printf("%19.15f\t%19.15f\n",x,y);
       }
    }
    

    There are also the possibility embed a scripting language, such as Lua or Python, which will give you (even) more power. This is something to consider if you're writing a game, since you'll likely want to script large parts of it.

    If you're using Qt, you can use QtScript (Javascript-ish) to run expressions that read (static or dynamic) properties from your QObject-derived objects.

    Using one of the above keeps you from having to write your own parser, AST and evaluator, however for a small set of operators it shouldn't be too hard to hack together something if you use Boost.Spirit or some other decent parsing library.

    Static expressions

    For selecting between a set of predefined expressions (i.e. known at compile time), you should store the expression in a polymorphic function object.

    For C++11, if that's available to you, use std::function and lambda expressions.

    std::function<bool (int, int)> expr = [](int a, int b) { a*2 < b };
    

    For earlier compilers, I recommend function and bind, either in Boost (boost::) or C++0x TR1 (std::), depending on your compiler. Also, Boost.Lambda will be of help here, as it allows you to construct and store expressions for later evaluation. However, if you're not familiar with C++ and templates (or functional programming), it will likely scare you quite a bit.

    With that you could write

    using namespace boost::lambda;
    boost::function<bool (int, int)> myexpr1 = (_1 + _2) > 20;
    boost::function<bool (int, int)> myexpr2 = (_1 * _2) > 42;
    std::cout << myexpr1(4,7) << " " << myexpr2(2,5);
    

    with bind, it'd look like:

    boost::function<bool (Player&)> check = bind(&Player::getHealth, _1) > 20;
    Player p1;
    if (check(p1)) { dostuff(); }
    
    check = bind(&Player::getGold, _1) < 42;
    if (check(p1)) { doOtherStuff(); }
    
    0 讨论(0)
  • 2020-12-13 15:26

    No, there isn't anything like that. Perhaps an expression class is a little too abstract. What about defining various Goal classes with an IsReached() method?

    0 讨论(0)
  • 2020-12-13 15:32

    There don't seem to be all that many recognised expression evaluation libraries for C++. I wrote my own for CSVfix which you can persuse by looking at the a_expr.h and a_expr.cpp files in the ALib library that forms part of the CSVfix source. The evaluator has not a great deal to recommend itself, except that it does the job and is (IMHO) fairly simple to understand.

    Unfurtunately, there is currently no public documentation for the evaluator, and by my own rule of thumb, that which is not documented cannot be reused. However, the unit tests show how it can be used, and the source may give you some ideas on implementing your own evaluator, should the fancy take you.

    0 讨论(0)
提交回复
热议问题