Assigning exprtk variables as vector members

306 views Asked by At

I asked very specific question here but I realized where the problem is and it's slightly more general. Seeing ALL exprtk examples and code pieces, everyone uses exprtk's basic metod add_variable as

double variab;
exprtk::symbol_table<double> my_symbol_table;
my_symbol_table.add_variable("name_of_variable", variab);

and never as

std::vector<double> variab{0.};
exprtk::symbol_table<double> my_symbol_table;
my_symbol_table.add_variable("name_of_variable", variab[0]);

Is there a reason? I cannot find anything on exprtk's readme.txt, it is just never mentioned, they switch immediately on adding a vector in the string expression corresponding to a c++ vector, which is not the case I want.

In my case I have several variables on the string with a random name and I want to match them on double variables inside a container . The example in the question linked seems to suggest that this doesn't work.

Any ideas?

1

There are 1 answers

0
ExprTk Developer On

Adding new values to a std::vector causes the underlying buffer to be reallocated/resized. This in turn results in the reference provided to the exprtk::symbol_table instance to be invalidated, which is the root cause of the issues you're seeing.

To resolve the issue either sufficiently reserve the size of the std::vector instance before adding symbols to the exprtk::symbol_table instance, or add all the entries to the vector first before adding them to the symbol_table.

Section 10.1 of the ExprTk Readme has the following series of scenarios that would cause similar issues:

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

symbol_table_t symbol_table;
expression_t   expression;

std::deque<double > y {1.1, 2.2, 3.3};
std::vector<double> z {4.4, 5.5, 6.6};
double* w = new double(123.456);

{
   double x = 123.4567;
   symbol_table.add_variable("x", x);
}             // Reference to variable x has been invalidated


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

y.pop_back(); // Reference to variable y has been invalidated


symbol_table.add_variable("z", z.front());

z.erase(z.begin());
              // Reference to variable z has been invalidated

symbol_table.add_variable("w", *w);

delete w;     // Reference to variable w has been invalidated

const std::string expression_str = "x + y / z * w";

              // Compilation of expression will succeed
parser.compile(expression_str,expression);

expression.value();
             // Evaluation will result in undefined behaviour
             // due to 'x' and 'w' having been destroyed.

symbol_table.get_variable("x")->ref() = 135.791;
             // Assignment will result in undefined behaviour