I wrote a C++ class that parses expressions like "2 * SQRT(5) + 1". I've created a class called c_function that "represents" the usual mathematical functions like sqrt, sin, cos etc. something like as follows:
class c_function { std::string name; double (*function)(double); public: c_function(std::string fname, double (*ffunction)(double)) { name = fname; function = ffunction; } // ... }; Then I have a different class that contains a std::vector of these c_function objects:
class expression { std::vector<c_function> functions; // etc... public: // ctor: expression(/* ... */) { // ... functions.push_back(c_function("SQRT", sqrt)); functions.push_back(c_function("SIN" , sin)); functions.push_back(c_function("COS" , cos)); // ... } }; The point is that all these functions have one argument. That is fine for most cases but I want to enable adding custom functions to the expression class and also want to support custom functions with more that one argument (for example, to define a function AREA(a, b) that returns the product of the two values a and b).
I did that by adding an argument counter argumentCount and more function "properties" to the c_function class:
class c_function { std::string name; unsigned int argumentCount; double (*function1)(double); double (*function2)(double, double); // ... }; and used two constructors:
c_function(std::string fname, double (*ffunction)(double)) { name = fname; argumentCount = 1; function1 = ffunction; function2 = NULL; }; c_function(std::string fname, double (*ffunction)(double, double)) { name = fname; argumentCount = 2; function1 = NULL; function2 = ffunction; }; and added the methods to the expression class:
// add custom function with one argument void addFunction(std::string fname, double (*ffunction)(double)); // add custom function with two arguments void addFunction(std::string fname, double (*ffunction)(double, double)); so that one can define
double Expression_Area(double width, double height) { return (width * height); } and introduce it to the expression class with
myExpression.addFunction("AREA", Expression_Area); That works fine and this way I can also add more function "properties" and functions constructors allowing any number of arguments, but
- there is always a limit of the number of arguments that is supported
- the code becomes ugly by having multiple constructors, methods to add a function, and code within the interpretation of the expression just because the number of arguments may be different.
I wonder if there is a way to support functions with any number of arguments more general. I tried changing the c_function class to:
class c_function { std::string name; unsigned int argumentCount; double (*function)(...); // ... }; but this does not work because functions with fixed number of arguments are not accepted by (...).
Is there any way to get this solved with one constructor, one function "property" etc.?