expresiones dinámicas
Si desea recibir una cadena del usuario y construyó una expresión de eso, tal vez el C++ Mathematical Expression Library se adapte a su proyecto de ley?
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);
}
}
Hay también la posibilidad de incrustar un lenguaje de script, como Lua o Python, que le dará (incluso) más potencia. Esto es algo que debes tener en cuenta si estás escribiendo un juego, ya que es probable que quieras guionar grandes partes de él.
Si está utilizando Qt, puede usar QtScript (Javascript-ish) para ejecutar expresiones que leen propiedades (estáticas o dinámicas) de sus objetos derivados de QObject.
El uso de uno de los anteriores le evita tener que escribir su propio analizador, AST y evaluador, sin embargo, para un pequeño grupo de operadores no debería ser demasiado difícil de hackear algo si usa Boost.Spirit o algún otro análisis decente biblioteca.
expresiones estáticas
para seleccionar entre un conjunto de expresiones predefinidas (es decir conocido en tiempo de compilación), debe almacenar la expresión en un objeto de función polimórfica.
Para C++ 11, si está disponible para usted, use std::function
y expresiones lambda.
std::function<bool (int, int)> expr = [](int a, int b) { a*2 < b };
Para compiladores anteriores, recomiendo función y se unen, ya sea en Boost (impulso: :) o C++ 0x TR1 (std: :), dependiendo de su compilador. Además, Boost.Lambda será de ayuda aquí, ya que le permite construir y almacenar expresiones para su posterior evaluación. Sin embargo, si no está familiarizado con C++ y las plantillas (o programación funcional), es probable que le asuste bastante.
Con eso se podría escribir
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);
con bind, se vería como:
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(); }
desafortunadamente, esto es completamente impráctico para expresiones arbitrarias. Lo cual creo que es lo que realmente quiere el afiche (a pesar de que su ejemplo sea "val1 op val2"). –
¿Lo es? Usando boost :: lambda puede combinar todo tipo de expresiones e incluso declaraciones y todo. ¿Qué quieres decir? – Macke
bien, ya que las lambdas de refuerzo se construyen en tiempo de compilación y solo son utilizadas por la persona que llama. ¿Qué harías si el usuario ingresara una combinación de operaciones que no hayas tenido en cuenta? Dado que hay un número infinito de combinaciones de operaciones matemáticas ... ciertamente no se puede explicar de manera estática para todas. –