Есть ли любой вид “класса выражения” (C++)

Я не буду давать ответ, но Стандартное Плохое Решение включает в себя использование переключателя или определения случая (или просто хорошего старомодного каскадного ввода-вывода). Немного лучшее решение предполагает использование таблицы указателей функций, а, вероятно, лучшее решение предполагает использование полиморфизма.

Последние двадцать лет эволюции интерпретаторов можно рассматривать как движение по другому пути - полиморфизм (например, наивные метациркулярные интерпретаторы Smalltalk) на функции указателей (реализации наивного lisp, многопоточного кода, C ++) для переключения ( наивные интерпретаторы байт-кода), а затем и далее в JIT и т. д., которые либо требуют очень больших классов, либо (в однополиморфных языках) двойной диспетчеризации, что сводит полиморфизм к регистру типов, и вы возвращаетесь на этап один. Какое определение 'best' используется здесь?

Для простых вещей полиморфное решение в порядке - вот то, что я сделал ранее , но либо стек и байт-код / ​​переключатель, либо использование компилятора среды выполнения обычно лучше, если вы, скажем, строите функцию с несколькими тысячами точек данных.

18
задан 10 June 2009 в 22:07
поделиться

8 ответов

Динамические выражения

Если вы хотите получить строку от пользователя и построить на ее основе выражение, возможно, вам подойдет Библиотека математических выражений 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 };

Для более ранних компиляторов я рекомендую функцию и привязку либо в 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);

с помощью bind, это ' d выглядит так:

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(); }
22
ответ дан 30 November 2019 в 08:58
поделиться

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
ответ дан 30 November 2019 в 08:58
поделиться

Не существует стандартного способа компиляции выражений во время выполнения. Вам придется сделать это другим способом.

Вы можете рассмотреть возможность использования языка сценариев, такого как Lua или Python, и встроить его в свой C ++. Это даст вашим игрокам возможность программировать так, как вы хотите.

1
ответ дан 30 November 2019 в 08:58
поделиться

C ++ не имеет этого как части языка - во время выполнения нет возможности получить доступ к тому же материалу, который анализировал вашу программу.

Я уверен однако существует множество сторонних библиотек арифметического анализатора, которые вы можете использовать.

0
ответ дан 30 November 2019 в 08:58
поделиться

Я думаю, вы можете определить свой собственный класс и обойти его, используя ключевое слово assert, но, возможно, я неправильно понял вопрос.

http : //www.cplusplus.com/reference/clibrary/cassert/assert/

0
ответ дан 30 November 2019 в 08:58
поделиться

Почему бы не создать свой собственный классы выражений?

class GoalBase
{
    virtual bool goal() = 0;
};

class Enemies : public GoalBase 
{
   // ..
   private:
      int enemies_;

   public:
      Enemies(int start) : enemies_(start) {}
      void kill() { if (enemies_) --enemies_; }
      bool goal() { return enemies_ == 0; }
};

int main()
{
    Enemies enemiesToKill(5);
    enemiesToKill.kill();    

    // ..
    if (enemiesToKill.goal()) {
        // ..
    }

    return 0;
}

Другие классы могут иметь другие методы, параметры, операторы и т. д. Используйте свое воображение.

0
ответ дан 30 November 2019 в 08:58
поделиться

Кажется, не так много признанных библиотек оценки выражений для C ++. Я написал свой собственный для CSVfix , который вы можете убедить, просмотрев файлы a_expr.h и a_expr.cpp в библиотеке ALib, которая является частью CSVfix. источник. Оценщику нечего рекомендовать, за исключением того, что он выполняет свою работу и (IMHO) довольно прост для понимания.

К сожалению, в настоящее время нет общедоступной документации для оценщика, и, по моему собственному практическому правилу, то, что не задокументировано, не может быть повторно использовано. Однако модульные тесты показывают, как его можно использовать, а исходный код может дать вам некоторые идеи по реализации вашего собственного оценщика, если вы захотите.

за исключением того, что он выполняет свою работу и (ИМХО) довольно прост для понимания.

К сожалению, в настоящее время нет общедоступной документации для оценщика, и, по моему собственному практическому правилу, то, что не задокументировано, не может быть повторно использовано. Однако модульные тесты показывают, как его можно использовать, а исходный код может дать вам некоторые идеи по реализации вашего собственного оценщика, если вы захотите.

за исключением того, что он выполняет свою работу и (ИМХО) довольно прост для понимания.

К сожалению, в настоящее время нет общедоступной документации для оценщика, и, по моему собственному практическому правилу, то, что не задокументировано, не может быть повторно использовано. Однако модульные тесты показывают, как его можно использовать, а исходный код может дать вам некоторые идеи по реализации вашего собственного оценщика, если вы захотите.

-3
ответ дан 30 November 2019 в 08:58
поделиться

В C ++ нет стандартного способа сделать это. Одно из решений - написать собственный парсер.

Еще одно решение, которое я бы порекомендовал: встроить интерпретатор Lua в вашу программу. Lua - это простой, но мощный язык программирования, который также имеет чрезвычайно легкий (<300 КБ) и простой в использовании интерпретатор. Прочтите вводную статью здесь: http://www.ibm.com/developerworks/linux/library/l-embed-lua/index.html

Внедрение Lua в вашу игру имеет ряд приятных побочных преимуществ. :

  • вы можете использовать его как мощный язык конфигурации для вашей игры
  • с Lua, вы может легко создать командную строку интерактивная среда, которая приятно для тестирования и экспериментов. Например, вы будете уметь менять игровой движок параметры и посмотреть эффект сразу, без перекомпиляции. Это особенно удобно для исследовательских проектов или программирования игр.
0
ответ дан 30 November 2019 в 08:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: