Please, tell me is it safe to call math functions the following way:
map<string,double(*)<double> func_map = { {"sin", &std::sin } ... }
...
double arg = 2.9;
double res = func_map["sin"](arg);
Please, tell me is it safe to call math functions the following way:
map<string,double(*)<double> func_map = { {"sin", &std::sin } ... }
...
double arg = 2.9;
double res = func_map["sin"](arg);
Taking the addresses of functions in the standard library not on the Designated addressable functions list leads to unspecified behavior (since at least C++20). std::sin and the other <cmath> functions are not on that list so, to be safe, wrap them up in functors, like lambdas:
#include <cmath>
#include <map>
#include <string>
int main() {
std::map<std::string, double(*)(double)> func_map = {
{"sin", [](double x) { return std::sin(x); }},
{"cos", [](double x) { return std::cos(x); }},
};
}
is it safe to call math functions the following way:
double res = func_map["sin"](arg);
No, if the function you aim to call is not present in func_map, using the subscript operator[] would first insert a double(*)(double) pointing at nullptr into the map and then return that nullptr. Calling nullptr(arg) would lead to undefined behavior. To make it safe you can do a couple of things:
func_map const. This prevents you from using any functions potentially inserting something in the map, like the subscript operator.func_map.at("sin")(arg); to get an exception (std::out_of_range) if the function doesn't exist in the map. You can safely catch that and print a message to the user:
try {
double res = func_map.at("sin")(arg);
std::cout << res << '\n';
} catch (const std::out_of_range& ex) {
std::cout << "unknown function\n";
}
find instead:
if(auto fit = func_map.find("sin"); fit != func_map.end()) {
double res = fit->second(arg);
std::cout << res << '\n';
} else {
std::cout << "unknown function\n";
}