将 void* 转换为 std::function<void()>
Convert void* to std::function<void()>
是将具有不同参数的函数指针存储在空指针向量中。
unordered_map<string, vector<void*> > List;
template <typename T>
void Listen(string Name, function<void(T)> Function)
{
List[Name].push_back(&Function);
}
然后我想调用它们,假设T
与用于Listen
的Fire
类型相同。
template <typename T>
void Fire(string Name, T Data)
{
auto Functions = List[Name];
for (auto i = Functions.begin(); i != Functions.end(); ++i)
{
(function<void(T)>)i)(Data);
}
}
但是我收到一个编译器错误,读取error C2064: term does not evaluate to a function taking 1 arguments in file ...vcincludexrefwrap 431 1
.
我做错了什么?
首先,您在此处获取参数的地址:
List[Name].push_back(&Function);
然后,您尝试在此处将迭代器对象转换为std::function
对象:
(function<void(T)>)i)
你想做的事情可以做到,就像这样,虽然它并不漂亮,但委婉地说:
unordered_map<string, vector<void*> > List;
template <typename T>
void Listen(string Name, function<void(T)> &Function)
{
List[Name].push_back(&Function);
}
template <typename T>
void Fire(string Name, T Data)
{
auto Functions = List[Name];
for (auto i = Functions.begin(); i != Functions.end(); ++i)
{
function<void(T)> *ptr = *i;
(*ptr) (Data);
}
}
它可以通过多种方式中断,例如,您无法控制在 Listen
中以某个名称注册的函数是否在 Fire
中使用正确的参数调用 - 考虑调用Listen<int> ("foo", f);
然后执行Fire<double> ("foo", 3.14);
另一种方法 - 只是传递回调的闭包:
unordered_map<string, std::vector<function<void()> > > List;
void Listen(string Name, function<void()> Function)
{
List[Name].push_back(Function);
}
void Fire(string Name)
{
auto Functions = List[Name];
for (auto i = Functions.begin(); i != Functions.end(); ++i)
(*i) ();
}
#include <functional>
#include <unordered_map>
#include <memory>
#include <string>
#include <vector>
template<typename T> struct BlockDeduction{typedef T type;};
struct BaseCallback {
virtual ~BaseCallback();
template<typename T>
void DoCall( typename BlockDeduction<T>::type&& t ) const;
};
template<typename T>
struct Callback: BaseCallback
{
std::function<void(T)> func;
Callback( std::function<void(T)> const& f ):func(f) {}
};
template<typename T>
void BaseCallback::DoCall( typename BlockDeduction<T>::type&& t ) const {
Assert( dynamic_cast<Callback<T>const*>(this) );
static_cast<Callback<T>const*>(this).func(std::forward(t));
}
typedef std::unique_ptr<BaseCallback> upCallback;
template<typename T>
upCallback make_callback( std::function<void(T)> const& f ) {
return upCallback( new Callback<T>( f ) );
}
struct Listener {
std::unordered_map< std::string, std::vector<upCallback>> List;
template<typename T>
void Listen( std::string Name, std::function<void(T)> f) {
List[Name].push_back( make_callback(f) );
}
template<typename T>
void Fire( std::string Name, typename BlockDeduction<T>::type&& t ) {
auto callbacks = List.find(Name);
if (callbacks == List.end()) return;
for(auto it = callbacks->second.begin(); it != callbacks->second.end(); ++it) {
if (it +1 = callbacks->second.end())
{
(**it).DoCall<T>( std::forward(t) );
} else {
(**it).DoCall<T>( t );
}
}
}
};
。或类似的东西。
这会在地图中存储std::function
的副本,通常包装。 内存通过unique_ptr
处理。 我小心翼翼地阻止了类型推断,在该点的类型必须与您安装Listener
时使用的类型完全相同(此时的自动类型推断相当脆弱)。
在调试中,如果违反 Name<-> 类型映射,则会导致断言失败。
对于空回调,需要做一些额外的工作。 只需编写一个将BaseCallback
强制转换为Callback<void>
的DoCall
,将Callback<void>
专用化为空function
包装器,专门function
make_callback
为调用裸DoCall
的Listener
编写Fire(string)
方法。
或者创建一个struct Empty
并使用lambdas将空函数包装在function<void(Empty)>
中,这将涉及稍微少一些代码,但在运行时会更慢。
- 为什么随机数生成器不在void函数中随机化数字,而在main函数中随机化
- 在c++类上调用void函数
- 为什么野牛仍在使用"int yylex(void)",却找不到"int yylex(YYS
- 在派生函数中指定void*参数
- C++为什么尽管我调用了void函数,它却不起作用
- 如何从void函数输出字符串
- 我应该使用什么来代替void作为变体中的替代类型之一
- 奇怪的结构&GCC&clang(void*返回类型)
- Arduino:for/while/if在void setup()或void loop()之前?——错误:之前需要不合格
- 为什么这个函数将"const char*"转换为"void* const"而不是"const void*"
- 引用一个已擦除类型(void*)的指针
- 将尾部调用void(i32,..)位转换为llvm::函数以获取FnAttribute
- 库函数需要一个 std::function<void(void)>,如何传入类函数?
- 如何将指针从一个void函数传递到另一个C++
- 为什么我在使用void函数时得到错误代码C2276
- EASTL矢量<向量<int>>连续的
- void*到驱动程序中的UnicodeString
- 为什么在逗号分隔符上下文中将预增量的结果强制转换为void
- 指针没有更新它在void函数内部指向的值
- 不能将 "void *" 类型的值分配给类型 "TCHAR" 的实体