C++ 将void*转换为std::function<;void()>;

C++ 将void*转换为std::function<;void()>;,c++,function,pointers,casting,std,C++,Function,Pointers,Casting,Std,将具有不同参数的函数指针存储在空指针向量中 unordered_map<string, vector<void*> > List; template <typename T> void Listen(string Name, function<void(T)> Function) { List[Name].push_back(&Function); } 但我得到了一个编译器错误,它读取错误C2064:term不会对文件中包含1个

将具有不同参数的函数指针存储在空指针向量中

unordered_map<string, vector<void*> > List;

template <typename T>
void Listen(string Name, function<void(T)> Function)
{
    List[Name].push_back(&Function);
}
但我得到了一个编译器错误,它读取
错误C2064:term不会对文件中包含1个参数的函数求值…\vc\include\xrefwrap 431 1


我做错了什么?

首先,您获取了一个参数的地址,如下所示:

List[Name].push_back(&Function);
然后尝试将迭代器对象转换为
std::function
对象:

(function<void(T)>)i)
#包括
#包括
#包括
#包括
#包括
模板结构块演绎{typedef T type;};
结构BaseCallback{
虚拟~BaseCallback();
模板
void DoCall(typename blockreduction::type&&t)const;
};
模板
结构回调:BaseCallback
{
std::函数func;
回调函数(std::function const&f):func(f){}
};
模板
void BaseCallback::DoCall(typename blockdeclusion::type&&t)const{
断言(动态_cast(this));
static_cast(this).func(std::forward(t));
}
typedef std::unique_ptr upCallback;
模板
upCallback make_回调(std::function const&f){
返回上回调(新回调(f));
}
结构侦听器{
std::无序映射List;
模板
void Listen(std::string Name,std::function f){
列表[名称]。推回(生成回调(f));
}
模板
无效火灾(标准::字符串名称、类型名称、类型和类型){
自动回调=List.find(Name);
if(callbacks==List.end())返回;
对于(自动it=callbacks->second.begin();it!=callbacks->second.end();++it){
if(it+1=callbacks->second.end())
{
(**it.DoCall(std::forward(t));
}否则{
(**it.DoCall(t);
}
}
}
};
。。。或者类似的

这将在映射中存储
std::function
的一个副本,并以一般方式包装。内存通过
唯一\u ptr
处理。我小心地在类型必须与安装
侦听器时使用的类型完全相同的地方阻止了类型推断(此时的自动类型推断相当脆弱)

在debug中,如果违反Nametype映射,将导致断言失败

需要为空回调做一些额外的工作。只需编写一个
DoCall
,将
BaseCallback
强制转换为
Callback
,专门化
Callback
为空
函数
包装,专门化
在空
函数
上生成回调
,并编写一个
激发(字符串)
调用裸
DoCall
侦听器的方法


或者创建一个
struct Empty
并使用lambdas将空函数包装到
函数中,这将涉及更少的代码,但在运行时会更慢。

您正在推送参数的地址。为什么不在
列表中保存
std::function
?@Lol4t0。遗憾的是,我不能在同一个列表中保存不同的类型。例如
函数
函数
函数
都是不同的类型。@chill。既然它是一个空指针向量,那有什么错呢?是的,但是在调用函数时你也无法确定函数的类型。
&
Listen
函数的参数上使用的是什么?我能以某种方式避免吗?这是为了确保使用左值调用函数,即使用具有地址的对象。仍然需要确保地址在向量/映射中保持有效。我喜欢这样,但我需要一些时间来真正理解您所做的一切。请注意,
std::forward
垃圾可能是错误的——我仍在尝试摸索。我可能不应该包括它,只是做了一些类型
t
的冗余副本<代码>块扣除
仅用于阻止自动功能类型扣除(因为
Fire
采用的
T
必须与
T
侦听
采用的类型或未定义的行为结果完全匹配)。
BaseCallback
确实存在是为了拥有一个虚拟dtor(因此调用了它的子类dtor),而
DoCall
方法只是将危险的
static\u cast
放入类中<代码>唯一\u ptr
管理生命周期。
(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);
    }
}
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 );
      }
    }
  }
};