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?
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:
using symbol_table_t = exprtk::symbol_table<double>;
using expression_t = exprtk::expression<double>;
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