简体   繁体   English

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

[英]Convert void* to std::function<void()>

Is store function pointers with different parameters in a vector of void pointers. 存储函数指针是否在void指针的向量中具有不同的参数。

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

template <typename T>
void Listen(string Name, function<void(T)> Function)
{
    List[Name].push_back(&Function);
}

Then I want to call them, assuming that T is the same type for Fire as used for the Listen . 然后我想调用它们,假设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);
    }
}

But I get a compiler error which reads error C2064: term does not evaluate to a function taking 1 arguments in file ...\\vc\\include\\xrefwrap 431 1 . 但是我得到一个编译器错误,它读取error C2064: term does not evaluate to a function taking 1 arguments in file ...\\vc\\include\\xrefwrap 431 1

What am I doing wrong? 我究竟做错了什么?

For one, you're taking the address of a parameter, here: 首先,您将获取参数的地址,此处:

List[Name].push_back(&Function);

Then you're trying to convert an iterator object to a std::function object here: 然后你试图在这里将迭代器对象转换为std::function对象:

(function<void(T)>)i)

What you trying to do can be done, like this, although it's not pretty, to put it mildly: 你可以做的就是这样,虽然它并不漂亮,但温和地说:

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

It can break in lot of ways, for example you have no control that the function, registered under some name in Listen is called with the correct argument in Fire - consider calling Listen<int> ("foo", f); 它可以在很多方面突破,例如,你无法控制的功能,在某些名义登记在Listen被称为在正确的说法Fire -要打电话Listen<int> ("foo", f); and then doing Fire<double> ("foo", 3.14); 然后做Fire<double> ("foo", 3.14);

Another approach - just pass closures for callbacks: 另一种方法 - 只需传递闭包回调:

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

... or something like that. ... 或类似的东西。

This stores a copy of the std::function in the map, wrapped up generically. 这将std::function的副本存储在地图中,一般包含在内。 Memory is handled via a unique_ptr . 内存通过unique_ptr处理。 I carefully blocked type deduction at points where the type must be exactly what you used when you installed the Listener (automatic type deduction at that point is rather fragile). 我小心地在类型必须与您在安装Listener时使用的类型一致时阻止了类型推导(此时自动类型推断相当脆弱)。

In debug, you'll get an assertion failure if you violate the Name<->type mapping. 在调试中,如果违反Name < - >类型映射,则会出现断言失败。

Some extra work needs to be done for nullary callbacks. 需要为Nullary回调做一些额外的工作。 Just write a DoCall that casts BaseCallback to Callback<void> , specialize Callback<void> to be a nullary function wrapper, specialize make_callback on nullary function , and write a Fire(string) method for Listener that calls the bare DoCall . 只写一个DoCall该投射BaseCallbackCallback<void> ,专门Callback<void>是一个无参function包装,专门make_callback上无参function ,并写一个Fire(string)用于方法Listener调用裸DoCall

Or create a struct Empty and use lambdas to wrap nullary functions in function<void(Empty)> , which would involve slightly less code, but would be slower at run-time. 或者创建一个struct Empty并使用lambdas在function<void(Empty)>包含nullary函数,这将涉及稍微少的代码,但在运行时会更慢。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 转换 std::function<void ()> 作废 (*)()</void> - Convert std::function<void ()> to void (*)() 使用void函数作为回调,从“ std :: function转换 <void ()> ? - Using a void function as a callback, convert from "std::function<void ()>? 错误:无法将&#39;print&#39;从&#39;void(*)(int)&#39;转换为&#39;std :: function <void()> “ - error: could not convert ‘print’ from ‘void (*)(int)’ to ‘std::function<void()>’ std :: is_same用于void函数(...)和void类型? - std::is_same for void function(…) and void type? 有没有办法将 void (*)(uint32_t, void (*)(uint32_t)) 转换为 std::function <void(uint32_t, std::function<void(uint32_t)> )&gt;?</void(uint32_t,> - Is there a way to convert void (*)(uint32_t, void (*)(uint32_t)) to std::function<void(uint32_t, std::function<void(uint32_t)>)>? 在具有不同签名的std :: function之间转换(T * arg到void * arg) - Convert between std::function with different signatures (T* arg to void* arg) 为什么我不能将[](auto &amp;&amp;…){}转换为std :: function <void()> ? - Why can't I convert [](auto&&…){} into a std::function<void()>? 无法将std :: bind的返回值转换为void函数指针 - unable to convert return value of std::bind to void function pointer 转换std :: function <void(Derived*)> 到std :: function <void(Base*)> - Converting std::function<void(Derived*)> to std::function<void(Base*)> 转换std :: function <void(string, string)> 到一个通用的std :: function <void()> - Converting std::function<void(string, string)> to a generic std::function<void()>
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM