映射到具有不同数量参数和不同数据类型的函数指针

Posted

技术标签:

【中文标题】映射到具有不同数量参数和不同数据类型的函数指针【英文标题】:map to a function pointer with different number of arguments and varying datatypes 【发布时间】:2020-08-06 07:17:27 【问题描述】:

在我的代码中,我有几个类,每个类都有不同的方法。例如:

class A 
public:
    int sum(int a, int b);
    bool isScalable(double d);


class B 
public:
    std:string ownerName();

我的目标是创建如下所有函数名称的映射

std::map<std::string, FnPtr> myMap;

// Add the newly implemented function to this map
myMap["sum"] = &A::sum;
myMap["isScalable"] = &A::isScalable;
myMap["myMap"] = &B::myMap;

问题是我不知道如何定义FnPtr。你能帮帮我吗?

【问题讨论】:

你想达到什么目的?您可以使用void * 作为类型并根据需要进行强制转换,但这通常是个坏主意。可能有更好的方法来解决您的潜在问题。 @BennyK:我想将每个函数映射到一个字符串。这是因为有来自应用程序外部的字符串格式的消息,我需要根据字符串调用函数。例如。调用sum(10,15),收到的消息是“sum 10 15” 见:this question。您可能不想这样做,调用这些函数中的任何一个都非常脆弱。 很难想出一个合理的方案来解决问题 只需在第一个单词上使用 switch case。 Switch 至少应该和 std::map 一样快。 【参考方案1】:

正如 cmets 所建议的,您不太可能真的想要这样做。

但是,假设您这样做了 - 也许您应该重新考虑 C++ 是否适合该任务。另一种具有更好的运行时反射功能的语言可能更合适;可能是 Python 或 Perl 等解释型语言。当您需要在运行时按名称查找类方法时,这些通常会更方便。

如果它必须是 C++,那么也许你应该稍微放宽类结构。对 A 和 B 使用一个类(我们称之为MyCommonObj);并让类持有一个字符串映射到函数指针。至于这些函数的签名 - 最好不要创建成员函数,而是独立的。在这种情况下,您的函数指针类型可能是:

using generic_function = std::any (*)(std::vector<std::any>);

这是非常通用的 - 用于存储和调用。如果你有这个映射,你可以很容易地查找你的函数名并传递参数。但是,您可能还需要保留有关您的参数应该是什么类型的其他信息,否则您将始终传递字符串。 ...我想这也是一种选择:

using generic_function = std::any (*)(std::vector<std::string>);

现在,如果您的示例中的 A 和 B 成员真的像您列出的那样是非静态的,即它们使用实例字段,那么这些通用函数也必须始终采用指向 MyCommonObj 实例的引用或指针:

using generic_function = std::any (*)(MyCommonObj&, std::vector<std::string>);

最后,请注意使用这种类型的代码,以及函数名的运行时查找等 - 性能不会很好。


如果您没有使用 C++17 并且无权访问 std::any,您可以:

使用 Boost 库中的 boost::any。 使用任意模拟器库(GitHub 上存在) 使用您实际使用的所有类型的并集,例如union int i; double d; - 但是你需要保护自己免受错误类型的值的传递。

【讨论】:

以上是关于映射到具有不同数量参数和不同数据类型的函数指针的主要内容,如果未能解决你的问题,请参考以下文章

为具有可变数量参数的不同函数编写通用包装器

使用具有抽象基类指针并调用派生类函数的映射

如何在R中的函数中有不同数量的具有默认值的参数?

如何在java中动态实例化具有不同数量参数的java类?

具有不同数量参数的函数中的 C++ 代码重复

调用具有不同数量参数的 cdecl 函数