动态表达式
如果您想从用户那里接收一个字符串并从中构建一个表达式,也许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
和 lambda 表达式。
std::function<bool (int, int)> expr = [](int a, int b) { a*2 < b };
对于早期的编译器,我建议使用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(); }