Получить вектор из exprTk в качестве вывода - PullRequest
2 голосов
/ 26 мая 2020

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

В настоящее время у меня есть следующее:

typedef double T; // numeric type (float, double, mpfr etc...)
typedef exprtk::symbol_table<T> symbol_table_t;
typedef exprtk::expression<T>     expression_t;
typedef exprtk::parser<T>             parser_t;

std::string expression_string = "var z[2] := { x, y };";

T x = T(5.3);
T y = T(2.3);
std::vector<T> z;

symbol_table_t symbol_table;
symbol_table.add_variable("x", x);
symbol_table.add_variable("y", y);
symbol_table.add_vector("z", z);

expression_t expression;
expression.register_symbol_table(symbol_table);

//Check if expression is valid
parser_t parser;
if (!parser.compile(expression_string, expression))
{
    printf("Compilation error...\n");
    return;
}

T result = expression.value();
std::cout << result << std::endl;     \\returns: 5.3 as expected the first element of vector z.
std::cout << z[0] << std::endl;       \\Crashes the program 

На выходе я хочу получить только вектор z. Как мне это сделать или что я делаю не так?

Ответы [ 2 ]

1 голос
/ 31 мая 2020

Согласно Раздел 20 - Возвращаемые значения выражений из readme . Можно немедленно выйти из выражения, возвращающего любое количество переменных любого типа, просто используя оператор возврата.

В документации представлен следующий пример:

std::string expression_string =
   " if (x < y)                                   "
   "   return [x + 1,'return-call 1'];            "
   " else if (x > y)                              "
   "   return [y / 2, y + 1, 'return-call 2'];    "
   " else if (equal(x,y))                         "
   "   x + y;                                     "
   " return [x, y, x + y, x - y, 'return-call 3'] ";

typedef exprtk::symbol_table<double> symbol_table_t;
typedef exprtk::expression<double>     expression_t;
typedef exprtk::parser<double>             parser_t;

symbol_table_t symbol_table;
expression_t   expression;
parser_t       parser;

double x = 0;
double y = 0;

symbol_table.add_variable("x",x);
symbol_table.add_variable("y",y);

expression.register_symbol_table(symbol_table);

parser.compile(expression_string,expression);

T result = expression.value();

if (expression.results().count())
{
   typedef exprtk::results_context<T> results_context_t;
   typedef typename results_context_t::type_store_t type_t;
   typedef typename type_t::scalar_view scalar_t;
   typedef typename type_t::vector_view vector_t;
   typedef typename type_t::string_view string_t;

   const results_context_t& results = expression.results();

   for (std::size_t i = 0; i < results.count(); ++i)
   {
      type_t t = results[i];

      switch (t.type)
      {
         case type_t::e_scalar : ...
                                 break;

         case type_t::e_vector : ...
                                 break;

         case type_t::e_string : ...
                                 break;

         default               : continue;
      }
}

Примечание1: Ваше выражение станет:

var z[2] := { x, y }; return [z];

Note2: Чтобы иметь свой «однострочный» метод, вы можете написать простую бесплатную функцию , которая обертывает код стандартной пластины после условного выражения и извлекает вектор на ваш выбор (i-й результат, учитывая его векторный тип) из списка results.

template <typename T>
bool get_vector(const std::size_t index, 
                const results_context_t& results,
                std::vector<T>& v)
{
   ...
}
1 голос
/ 28 мая 2020

Я нашел метод, который действительно работает, но, надеюсь, есть более простой «однострочный» метод

std::string expression_string = "var w[2] := { x, y }; z := w";

Это создает локальный вектор выражения w ([РАЗДЕЛ 13 - ПЕРЕМЕННАЯ, ОПРЕДЕЛЕНИЕ ВЕКТОРА И СТРОКИ]), а затем присваивает значение z

Как упоминал @NathanOliver, std::vector<T> z(2); также требуется


"var z[2] := { x, y };" не работает как это недопустимое переопределение переменной z из-за использования оператора var.

Обратите внимание, что "z := {x, y}" также не будет работать, поскольку это не похоже на допустимое выражение присваивания для вектор


Вывод (с включенной отладкой):

prev[var] --> curr[var]
prev[var] --> curr[w]
prev[2] --> curr[]]
prev[x] --> curr[,]
prev[y] --> curr[}]
parse_define_vector_statement() - INFO - Added new local vector: w[2]
activate_side_effect() - caller: parse_define_vector_statement()
parse_corpus(00) Subexpr: var w[2] := { x, y };
parse_corpus(00) - Side effect present: true
-------------------------------------------------
prev[z] --> curr[:=]
prev[:=] --> curr[w]
prev[w] --> curr[]
activate_side_effect() - caller: lodge_assignment()
parse_corpus(01) Subexpr: z := w
parse_corpus(01) - Side effect present: true
-------------------------------------------------
5.3
5.3
...