Динамические выражения
Если вы хотите получить строку от пользователя и построить из нее выражение, может быть, Библиотека математических выражений C ++ подходит для вашего счета?
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);
}
}
Существует также возможность встроить язык сценариев, например Lua или Python , что даст вам (даже) больше возможностей. Это то, что нужно учитывать, если вы пишете игру, так как вы, вероятно, захотите написать сценарий для больших ее частей.
Если вы используете Qt , вы можете использовать QtScript (Javascript-ish) для запуска выражений, которые читают (статические или динамические) свойства из ваших производных от QObject объектов.
Использование одного из вышеперечисленных избавляет вас от необходимости писать собственный синтаксический анализатор, AST и оценщик, однако для небольшого набора операторов не составит труда собрать что-то вместе, если вы используете Boost.Spirit или какая-то другая приличная библиотека для разбора.
Статические выражения
Для выбора между набором предопределенных выражений (т.е. известных во время компиляции) вы должны сохранить выражение в объекте полиморфной функции.
Для C ++ 11, если это доступно для вас, используйте std::function
и лямбда-выражения.
std::function<bool (int, int)> expr = [](int a, int b) { a*2 < b };
Для более ранних компиляторов я рекомендую function и bind либо в Boost (boost: :) или C ++ 0x TR1 (std: :), в зависимости от вашего компилятора. Также здесь поможет Boost.Lambda, поскольку он позволяет создавать и хранить выражения для последующей оценки. Однако, если вы не знакомы с C ++ и шаблонами (или функциональным программированием), это, скорее всего, вас немного напугает.
С этим вы могли бы написать
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);
с привязкой, это будет выглядеть так:
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(); }