当前位置: 首页 > 知识库问答 >
问题:

在映射中存储具有不同签名的函数

慕容聪
2023-03-14

我试图在C++中创建一个映射字符串作为键,泛型方法作为value,但我不知道这是否可能。我想做这样的事情:

void foo(int x, int y)
{
   //do something
}

void bar(std::string x, int y, int z)
{
   //do something
} 

void main()
{
   std::map<std::string, "Any Method"> map;

   map["foo"] = &foo;      //store the methods in the map
   map["bar"] = &bar;

   map["foo"](1, 2);       //call them with parameters I get at runtime
   map["bar"]("Hello", 1, 2);
}

这可能吗?如果是,我如何实现这一点?

共有1个答案

杜阳炎
2023-03-14

您可以在容器中键入-擦除函数类型,然后提供一个模板操作符()。如果您弄错了,这将抛出std::bad_any_cast

N.B.由于类型擦除,您必须在调用站点指定完全匹配的参数,例如std::function std::function 不同,尽管两者都可以使用类似“hello”这样的值调用。

#include <any>
#include <functional>
#include <map>
#include <string>
#include <iostream>

template<typename Ret>
struct AnyCallable
{
    AnyCallable() {}
    template<typename F>
    AnyCallable(F&& fun) : AnyCallable(std::function(fun)) {}
    template<typename ... Args>
    AnyCallable(std::function<Ret(Args...)> fun) : m_any(fun) {}
    template<typename ... Args>
    Ret operator()(Args&& ... args) 
    { 
        return std::invoke(std::any_cast<std::function<Ret(Args...)>>(m_any), std::forward<Args>(args)...); 
    }
    std::any m_any;
};

template<>
struct AnyCallable<void>
{
    AnyCallable() {}
    template<typename F>
    AnyCallable(F&& fun) : AnyCallable(std::function(fun)) {}
    template<typename ... Args>
    AnyCallable(std::function<void(Args...)> fun) : m_any(fun) {}
    template<typename ... Args>
    void operator()(Args&& ... args) 
    { 
        std::invoke(std::any_cast<std::function<void(Args...)>>(m_any), std::forward<Args>(args)...); 
    }
    std::any m_any;
};

void foo(int x, int y)
{
   std::cout << "foo" << x << y << std::endl;
}

void bar(std::string x, int y, int z)
{
   std::cout << "bar" << x << y << z << std::endl;
} 

using namespace std::literals;

int main()
{
   std::map<std::string, AnyCallable<void>> map;

   map["foo"] = &foo;      //store the methods in the map
   map["bar"] = &bar;

   map["foo"](1, 2);       //call them with parameters I get at runtime
   map["bar"]("Hello, std::string literal"s, 1, 2);
   //map["bar"]("Hello, const char *literal", 1, 2); // bad_any_cast
   map["bar"].operator()<std::string, int, int>("Hello, const char *literal", 1, 2); // explicit template parameters

   return 0;
}
 类似资料:
  • 问题内容: 如何创建具有不同签名的函数片段?我尝试了下面的代码,但感觉有点黑。我们只是硬着头皮使用切片界面{}吗? 这仅仅是尝试对Golang做太多事情的一种情况吗? 问题答案: 请检查它,我不知道它是否想要什么。因为我不知道你到底想要什么。 在Go Playground 上检查 在这里,我有另一个使用反射调用的示例 在Go Playground 上检查

  • 我会从我想达到的目标开始 意图 该软件在for循环中解析XML数据。处理数据的 for 循环将持续到 50(因为我得到了 50 个不同的结果)。我最初所做的是,-方法解析整个XML数据并将其保存到TextViews中并显示它。但现在我想添加一个启动画面,只要数据加载就会显示。 XML文件像任何其他普通XML文件一样构建,因此当我通过for循环时,键总是相同的,但值不同。 方法 我已经做的是创建一个

  • 问题内容: 我有一个超类的方法: 在其子类之一中,我想执行以下操作: 但这是行不通的。问题是我有一个超类的引用,并且我想只在其中一个子类中调用此方法。 问题答案: 您不能在重写方法中更改类型参数的数量。对于您的情况,返回类型显然会覆盖失败。但是,即使返回类型相同,您的方法仍然不会被覆盖等效,因为您应该覆盖的方法中的类型参数更少。 从JLS- 方法签名 : 如果两个方法具有相同的名称和参数类型,则它

  • 问题内容: 我有三个类:,和。 继承自和(按此顺序)。的构造特征和不同。如何调用两个父类的方法? 我在代码中的努力: 产生错误: 我发现此资源用不同的参数集解释了多重继承,但他们建议对所有参数使用和。我觉得这很丑陋,因为我无法从子类的构造函数调用中看到将哪些参数传递给父类。 问题答案: 千万 不能* 使用,除非你知道自己在做什么。第一个参数告诉它寻找下一个要使用的方法时要 跳过的 类。例如,将查看

  • 我的应用程序只是一个看起来像这样的简单清单 ReactJS中的map函数有一些奇怪的行为。 每当我打印出来以检查值是否确实用console.log(todo.completed)更改时,它会在控制台中打印出正确的值,但随后我尝试打印出整个对象列表,突然它又回到了原来的状态。在本例中,我单击了选项1 这是我打印出常量updatedItems时的结果 我可以改变任何其他属性没有任何麻烦,我甚至可以设置

  • 我有两个数据格式不同但值相同的表。 表一: 表二: 表1和表2之间的关系是多对一。此表的值与上面的日期格式相同。我现在的任务是映射这些表。我如何在ERD图中显示这些。我必须创建一个新表吗?