Eric Johnson
Eric Johnson

Reputation: 826

Wih exprtk, what is the correct way to create a vector based variable from within an unknown_symbol_resolver?

The exprtk documentation provides a great example on how to create a scalar variable from an unknown_symbol_resolver. How to do I create a vector? I would expect to find a create_vector member function on the symbol_table class, but there is none.

Consider a simple program that takes an exprtk formula from the command line. In my example, I'd like to have foobar created as a variable instead of a scalar.

./a.out "return [ foobar ]; "

The program.

#include <string>
#include <stdio.h>
#include <vector>
#include "exprtk.hpp"

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

template<typename T>
struct myusr : public parser_t::unknown_symbol_resolver {

  using usr = typename parser_t::unknown_symbol_resolver;

  myusr() : usr(usr::e_usrmode_extended) { }
  virtual bool process(const std::string &symbol, symbol_table_t &symbol_table, std::string &) {
    printf("Handling symbol: %s\n", symbol.c_str());
    symbol_table.create_variable(symbol, 4.14);
    return true;
  }
};

int main(int argc, char **argv) {

  symbol_table_t symbol_table;
  symbol_table.add_constants();

  expression_t expression;
  expression.register_symbol_table(symbol_table);

  parser_t parser;
  myusr<double> lookup;
  parser.enable_unknown_symbol_resolver(&lookup);
  if (!parser.compile(argv[1], expression)) {
    printf("Compilation error: %s\n", argv[1]);
    return -1;
  }
  return 0;
}

Upvotes: 6

Views: 58

Answers (1)

Eric Johnson
Eric Johnson

Reputation: 826

The answer appears to be that rather than expect a functional create_vector member function, one can just use add_vector. However, its critical to provide a vector with at least one element and the vector must have storage beyond the lifetime of the invocation of the unknown_symbol_resolver::process member function.

By way of an example. One could write it like this.

 virtual bool process(const std::string &symbol, symbol_table_t &symbol_table, std::string &) {
   static std::vector<T> x;
   x.push_back(3.14);
   symbol_table.add_vector(symbol, x);
   return true;
 }

Of course, this example is in some ways terrible, because the static scoped storage for x would be shared for every unknown variable.

Upvotes: 5

Related Questions