在地图中存储具有不同签名的功能 [英] Store functions with different signatures in a map

查看:57
本文介绍了在地图中存储具有不同签名的功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 string 作为键并使用映射在C ++中> value ,但我不知道这是否有可能。我想做这样的事情:

I am trying to create a map with string as key and a generic method as value in C++, but I do not know if that is even possible. I would like to do something like that:

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);
}

有可能吗?如果是,我如何实现?

Is that possible? If yes, how can I realise this?

推荐答案

您可以将函数类型键入-擦除到容器中,然后提供模板 operator()。如果错误,则会抛出 std :: bad_any_cast

You can type-erase the function types into a container, then provide a template operator(). This will throw std::bad_any_cast if you get it wrong.

N.B。由于类型擦除,您将必须在调用网站上指定完全匹配的参数,例如 std :: function< void(std :: string)> std :: function< void(const char *)> ,即使两者都可以用 Hello 之类的值调用。

N.B. because of the type erasure, you will have to specify exactly matching arguments at the call site, as e.g. std::function<void(std::string)> is distinct from std::function<void(const char *)>, even though both can be called with a value like "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;
}

这篇关于在地图中存储具有不同签名的功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆