Home > Net >  Is it safe to call <math.h> functions by reference?
Is it safe to call <math.h> functions by reference?

Time:05-19

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";
    }
    
  • Related