基于字符串输入调用函数

Call a function based on string input

本文关键字:调用 函数 输入 字符串      更新时间:2023-10-16

我想这可以被描述为"插入式架构"问题。

此刻我有一个代码写在c++需要调用一个特定的函数(在优化例程的适应度函数)。以前,这需要大量的代码复制,这使得我发现bug时的维护成为一场噩梦。因此,我已经设法压缩了代码,这样除了各种适应度函数之外,我只有一个东西,这显然是不能压缩的。

这些适应度函数没有共享名称,也不需要共享名称。我设置它的方式是,优化例程调用一个"主"适应度函数,该函数在输入字符串和函数的硬编码"名称"之间执行字符串比较。即:

FitFunc myMainFit(double* inp, int d) {
    double retVal;
    if (inName == "func1") {
        retVal = myFitOne(inp, d);
    } else if (inName == "func2") {
        retVal = myFitTwo(inp, d);
    // Other comparisons ...
    } else {
        std::cout << "Unknown Function" << std::endl;
        retVal = -1;
    }
    return retVal;
}

我想做的是有一种方法来动态地创建这些比较,这样我就不必在每次我想要使用一个新函数时更新一堆东西。

目前,我的适应度函数都在一个目录中,并且具有一些共同的命名特征,包括与其包含的函数具有相同的名称。例如:myFitTwo.cpp包含myFitTwo(double*, int)

我的想法是,我可以在我的makefile中添加一个步骤,以便在编译时生成上述代码块,以及在所包含的hpp文件中生成必要的函数定义。

这是最好的方法吗?是否有更好的方法,或者是最好的选择只是继续,因为我一直和手动添加功能,因为我创建它们?我并没有创建大量的,也没有非常频繁地创建它们,但是自动化这个过程感觉更不容易出错。我还希望能够将此代码提供给同事,并希望他能够添加函数,而不必在其余文件中瞎折腾。

您可以使用std::map<std::string, FUNCPTR>,其中FUNCPTR是函数指针的别名。例子:

#include <iostream>
#include <string>
#include <map>
typedef void(*FUNCPTR)(double*, int); // our typedef
std::map<std::string, FUNCPTR> func_map;
// some functions
void f1(double*, int) {std::cout << "f1" << std::endl;}
void f2(double*, int) {std::cout << "f2" << std::endl;}
// call them via an invoking function
void myMainFit(const std::string& which, double* ptr, int val)
{
    if(func_map.find(which)!= func_map.end()) // indeed the function was added
        func_map[which](ptr, val);
    else
    {
        std::cerr << "Function "" << which << "" is not in the map!n";
        return; // or throw
    }
}
int main()
{
    // add functions to the map
    func_map["first"] = &f1;
    func_map["second"] = &f2;
    myMainFit("first", nullptr, 42);
    myMainFit("second", nullptr, 20);
    myMainFit("inexistent", nullptr, 10);
}

Live on Ideone

正如@David Haim所提到的,您可以使用std::unordered_map (c++ 11)来加快速度,因为后者是一个哈希表,并且它已经平摊了O(1)访问时间。