動的表現
ユーザーから文字列を受け取り、そこから式を作成したい場合は、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 っぽい) を使用して、QObject 派生オブジェクトから (静的または動的) プロパティを読み取る式を実行できます。
上記のいずれかを使用すると、独自のパーサー、AST、およびエバリュエーターを作成する必要がなくなりますが、少数のオペレーターのセットの場合、Boost.Spiritまたは他の適切な解析ライブラリを使用すれば、何かを一緒にハックするのはそれほど難しくありません。
静的式
定義済みの式 (つまり、コンパイル時に既知) のセットから選択するには、式を多相関数オブジェクトに格納する必要があります。
C++11 の場合、利用可能な場合はstd::function
、ラムダ式を使用します。
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(); }