c – 使用不同参数的std ::函数的集合
作者:互联网
我正在尝试编写一个简单的调度程序,用户代码可以将回调附加到它.
每个事件都有一个已知的签名,用户代码需要使用正确的数字和参数类型调用dispatch.这由可变参数管理.但是,freestandingInt不被接受,因为向量不是正确的类型.如何使它通用?
遵循一个最小的例子
void freestanding() {
std::cout << "freestanding" << std::endl;
}
void freestandingInt(int iArg) {
std::cout << "freestandingInt " << iArg << std::endl;
}
struct Dispatcher {
typedef struct Event_ {
std::vector<std::function<void()> > listeners;
} Event;
template<class... Args>
void dispatch(int eventNr, Args&&... args) {
for (auto listener: events[eventNr].listeners) {
std::function<void()> f(std::bind(listener, std::forward<Args>(args)...));
f();
}
}
std::map<int, Event> events;
};
int main (int argc, char **argv) {
Dispatcher disp;
disp.events[0].listeners.push_back(freestanding);
disp.dispatch(0); // OK
// error here
//disp.events[1].listeners.push_back(freestandingInt);
}
解决方法:
这是一种基于将std :: multimap从函数的std :: type_index转换为适当类型的std :: function的方法:
#include <functional>
#include <iostream>
#include <map>
#include <memory>
#include <typeindex>
void freestanding() {
std::cout << "freestanding" << std::endl;
}
void freestandingInt(int iArg) {
std::cout << "freestandingInt " << iArg << std::endl;
}
// Base class for all functions so that we can store all functions
// in a single container.
struct Function {
virtual ~Function() { }
};
// Derived class template for functions with a particular signature.
template <typename T>
struct BasicFunction : Function {
std::function<T> function;
BasicFunction(std::function<T> function) : function(function) { }
};
// Generic container of listeners for any type of function
typedef std::multimap<std::type_index,std::unique_ptr<Function> > Listeners;
template <typename Func>
static void addListener(Listeners &listeners,Func &function)
{
std::type_index index(typeid(Func));
std::unique_ptr<Function>
func_ptr(new BasicFunction<Func>(std::function<Func>(function)));
listeners.insert(Listeners::value_type(index,std::move(func_ptr)));
}
template <typename... Args>
static void callListeners(const Listeners &listeners,Args&&... args)
{
typedef void Func(typename std::remove_reference<Args>::type...);
std::type_index index(typeid(Func));
Listeners::const_iterator i = listeners.lower_bound(index);
Listeners::const_iterator j = listeners.upper_bound(index);
for (;i!=j; ++i) {
const Function &f = *i->second;
std::function<Func> func =
static_cast<const BasicFunction<Func> &>(f).function;
func(std::forward<Args>(args)...);
}
}
struct Dispatcher {
typedef struct Event_ {
Listeners listeners;
} Event;
template<class... Args>
void dispatch(int eventNr, Args&&... args) {
callListeners(events[eventNr].listeners,std::forward<Args>(args)...);
}
std::map<int, Event> events;
};
int main (int argc, char **argv) {
Dispatcher disp;
addListener(disp.events[0].listeners,freestanding);
addListener(disp.events[0].listeners,freestandingInt);
disp.dispatch(0,5);
}
输出:
freestandingInt 5
标签:std-function,c,c11,variadic-templates 来源: https://codeday.me/bug/20190929/1830611.html