在地图中存储具有不同签名的功能 [英] Store functions with different signatures in a map
问题描述
我正在尝试使用 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屋!