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);
CodePudding user response:
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:
- Make
func_map
const
. This prevents you from using any functions potentially inserting something in the map, like the subscript operator. - Use
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"; }
- If you don't want exceptions for unknown functions, you can use the member function
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"; }