通过引用调用 <math.h> 函数是否安全?

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

请告诉我按以下方式调用数学函数是否安全:

map<string,double(*)<double> func_map = { {"sin", &std::sin } ... }
...
double arg = 2.9;
double res = func_map["sin"](arg);

获取标准库中不在 Designated addressable functions 列表中的函数地址会导致未指定的行为(至少自 C++20 起)。 std::sin 和其他 <cmath> 函数不在该列表中,因此,为了安全起见,将它们包装在函子中,例如 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);

否,如果您要调用的函数不在 func_map 中,请使用下标 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。为了确保安全,您可以做几件事:

  • 制作func_mapconst。这可以防止您使用任何可能在地图中插入内容的函数,例如下标运算符。
  • 如果映射中不存在该函数,则使用 func_map.at("sin")(arg); 获取异常 (std::out_of_range)。您可以安全地捕获它并向用户打印一条消息:
    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代替:
    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";
    }