我真的需要你的帮助。因为我是一个初学者,我被困在存储回调与variadic参数。
目标是存储x个回调函数和它们的n个y类型的参数。我试着用模板,但坚持他们的演绎。回调需要在我现有的静态库中由其他事件触发,这些事件更改回调参数。所有的回调函数都将/必须返回void。
在我的main.cpp中,我需要:
void testFunc_i(int i){
//do something
}
void subscribe_i(){
myLib::registerCallback(
"something", "INT",
&testFunc_i
);
}
void testFunc_ivf(int i, std::vector<float> f){
//do something
}
void subscribe_ivf(){
myLib::registerCallback(
"another string", "INT",
"something different", "FLOAT[]",
&testFunc_ivf
);
}
void testFunc_ifs(int i, float f, std::string s){
//do something
}
void subscribe_ifs(){
myLib::registerCallback(
"foo", "INT",
"bar", "FLOAT",
"text", "STRING",
&testFunc_ifs
);
}
int main(int argc, char** argv)
{
subscribe_i();
subscribe_ivf();
subscribe_ifs();
}
我在myLib中的内容是这样的:
namespace myLib{
class Subscriber
{
public:
Subscriber();
~Subscriber();
void addString(const std::string &s)
{
v.push_back(s);
}
void addType(const std::string &s)
{
t.push_back(s);
}
void setCallback(callback_t callbackFn) //???
{
callback = callbackFn; // ???
}
void call( /* ??? */ )
{
// ???
callback(); // ???
}
private:
callback_t callback; // ???
std::vector<std::strings>v;
std::vector<std::strings>t;
};
// if argument is a string
void add(unsigned &cnt, auto* subscriber, const std::string &value)
{
if (cnt%2==0) {
subscriber->addString(value);
}else{
subscriber->addType(value);
}
cnt++;
}
// if argument is a function
template <typename... Args>
void add(unsigned &cnt, auto* subscriber, void(*_callbackFn)(Args...) )
{
subscriber->setCallback(_callbackFn);
}
template <typename... Ts>
void registerCallback(Ts&&... ts)
{
auto subscriber = new Subscriber();
unsigned cnt = 0;
auto dummy = {(add(cnt,subscriber,ts), 0)...};
Store::getInstance().addSubsriber(subscriber); //store the subscriber object in a Singleton (working)
}
}
2条答案
按热度按时间icnyk63a1#
你不能这样做。
如果在函数中使用可变参数,最好的办法是将这些参数转换为元组。
然而,一个元组与具有任何不同参数列表的任何其他元组都不同,因此您不能将其存储在容器中以便稍后回调。
如果元组是从一个公共基类派生的,那么您就可以在使用之前存储它们(这必须通过一个
virtual call()
方法进行双重分派)。这样写起来不太方便,因为这意味着几乎要重写std::tuple
类型。如果我是你,我会做相反的事情,也就是说,做一个lambda来调用传递的回调函数,并将它转换为
std::function
存储在容器中,以备以后调用。沿着伪代码(未测试):
这种代码总是非常不安全的,因为参数的类型可以是引用(语法中没有任何东西可以阻止这种情况)。当稍后回调时,引用的对象可能不再存在。如果你不得不写一个库,你最好避免这样做,相反,让你的接口非常严格,以防止这种情况。
不安全使用示例:
0qx6xfy62#
你可以这样做。
希望有帮助:-)(我正在使用Qt,可以用std替换qt容器)
欢迎来电。
您可能希望编辑
call
来检查回调是否存在,否则返回nullptr或类似的东西。..C++存储带有可变参数的回调并获取返回