创建带有任何参数的 std::functions 的unordered_map?
Creating an unordered_map of std::functions with any arguments?
我正在尝试创建一个无序的std::functions
图。其中键是一个字符串,您将在其中查找要调用的函数,函数是值。
我写了一个小程序:
#include <iostream>
#include <unordered_map>
#include <functional>
#include <string>
void func1()
{
std::cout << "Function1 has been called." << std::endl;
}
int doMaths(int a)
{
return a + 10;
}
int main()
{
std::unordered_map<std::string,std::function<void()>> myMap;
myMap["func1"] = func1;
}
这编译得很好,我可以通过放置以下命令调用该函数(但是我不确定这是否是正确的方法):
auto mapIter = myMap.find("func1");
auto mapVal = mapIter->second;
mapVal();
然后调用函数,但是我认为这是以创建函数的新副本为代价的?如果我错了,请纠正我。
但是,如果我尝试这样做:myMap["doMaths"] = doMaths;
我会收到编译器错误,因为myMap
中的值是std::function<void()>>
而不是std::function<int(int)>>
.当我这样做时,我确实得到了这个编译:myMap["doMaths"] = std::bind(doMaths,int());
但是我不知道这实际上做了什么。当我尝试以与func1
相同的方式调用它时,我得到一个编译器错误。
所以我想我有两个问题:
如何创建一个将采用任何类型的函数作为其值的unordered_map?如何在映射中调用函数而无需复制函数?
正如 eerorika 所说,你可以用一张std::any
地图来做到这一点。 下面是一些示例代码,还显示了如何调用存储在映射中的函数指针:
#include <iostream>
#include <unordered_map>
#include <string>
#include <any>
void func1()
{
std::cout << "Function1 has been called.n";
}
int doMaths(int a)
{
std::cout << "doMaths has been called, a = " << a << "n";
return a + 10;
}
int main()
{
std::unordered_map<std::string,std::any> myMap;
myMap["func1"] = func1;
auto mapIter = myMap.find("func1");
std::any_cast <void (*) ()> (mapIter->second) ();
myMap["doMaths"] = doMaths;
mapIter = myMap.find("doMaths");
int result = std::any_cast <int (*) (int)> (mapIter->second) (5);
std::cout << result;
}
现场演示
如果类型(在本例中为函数签名)不匹配,std::any_cast
将在运行时引发std::bad_any_cast
异常。
请注意:std::any
需要C++17,请参阅:https://en.cppreference.com/w/cpp/utility/any
如果你知道你的函数的类型是std::function<void(void)>
,把它放在一个std::unordered_map<std::string,std::function<void()>>
中,然后在那里查找。
如果你知道你的函数类型是std::function<int(double, char)>
,把它放在一个std::unordered_map<std::string,std::function<int(double, char)>>
里,然后在那里查找。
如果你不知道你的函数的类型,你就无法使用它,所以把它存储在地图中也是没有用的。
如果您有多种类型的函数,则还要具有多个映射。变量模板(或具有静态映射变量的函数模板)可以帮助拥有任意数量的此类映射,而无需复制任何代码。当然,这样你只能有一个全球地图。可以管理此类地图集合的类可能会涉及更多内容,但只是一点点。
就像保罗说的那样,但语法std::function
。您可以使用它来将带有任何签名的函数放入映射中,甚至是 lambda :D
#include <vector>
#include <iostream>
#include <functional>
#include <map>
#include <any>
int doMaths(int a)
{
std::cout << "doMaths has been called, a = " << a << "n";
return a + 10;
}
int main()
{
std::map<std::string, std::any> map;
map["foo"] = std::function<int(int)>([](int a) { return a * 2; });
map["bar"] = std::function<int(int, int)>([](int a, int b) { return a + b; });
map["maths"] = std::function<int(int)>(doMaths);
int a = std::any_cast<std::function<int(int)>>(map["foo"])(4);
int b = std::any_cast<std::function<int(int, int)>>(map["bar"])(4, 5);
int c = std::any_cast<std::function<int(int)>>(map["maths"])(5);
std::cout << a << " " << b << " " << c <<std::endl;
}
投射时要小心,您需要知道正确的签名和返回类型。
- 如何在Google Cloud Functions上运行C++文件?
- "thread-safe data"与"thread-safe code/functions"的区别
- 有没有办法扩展和调用 std::functions 的元组?
- C++ Functions & Arrays - Visual Studios 中的错误 C4700
- Protobuf 生成的C++类无法针对 iOS 进行编译,并显示错误"Only virtual member functions can be marked 'final'"
- StringCch* functions and Cstring
- Call std::functions
- "Default member initializer needed within definition of enclosing class outside of member functions
- TicTacToe C++ functions
- 创建带有任何参数的 std::functions 的unordered_map?
- 将lambdas/functions存储在std::vector中,而不使用std::function
- 如何让 CMake 编译包含 Boost Local Functions 的源文件
- "All arguments to functions are passed by value" C 中的,C++ 中对引用传递的混淆
- 是否可以<int>在一行中将向量值分配给 std::unordered<int,std::vector<int>>?
- 犰狳/ Xcode:无处"functions that differ only in their return type cannot be overloaded"错误
- boost::bind with member functions(作为boost::asio异步写入处理程序)
- "functions"对话框过程中的过程
- "Only non-static member functions may be virtual"
- C++ "Virtual functions handling on multiple base classes"
- QML - Q_INVOKABLE functions