I want to save and pass list of template arguments to function.
Like std::thread
passes arguments to a thread. Types of arguments are templated and arguments count is not static.
Example, how it will work:
class CallbackList {
public:
Callback(/* Type of list of template args */ args) {
this->saved_args = args;
}
void Call() {
this->callback(saved_args);
}
private:
/* Type of list of template args */ saved_args;
CallbackType callback;
}
Or how can I implement that:
template<typename ...Args>
class CallbackList {
public:
using CallbackPrototype = /* some prototype */;
void RegisterCallback(CallbackPrototype callback, Args... args) {
CallbackInfo callback_info;
callback_info.callback = callback;
callback_info.args = { args... };
this->callbacks.push_back(callback_info);
}
void Call() {
for (CallbackInfo& callback_info : this->callbacks)
callback_info.callback(callback_info.args);
}
private:
struct CallbackInfo {
CallbackPrototype callback;
/* what type should be here? tuple? args count are not static */ args;
};
std::vector<CallbackInfo> callbacks;
}
It is possible?
How can I implement it?
If you do not want your callback to depend on the types of the arguments you have to use some kind of type erasure. You can, for example, use std::function
from <functional>
:
#include <functional>
#include <iostream>
class Lazy_Callback
{
public:
template <typename F, typename ...Args>
Lazy_Callback(F && f, Args && ...args)
: _fun([=]() { return f(args...); })
{ }
void call() const
{
_fun();
}
protected:
private:
std::function<void()> _fun;
};
void print_int(int x)
{
std::cout << "x = " << x << "\n";
}
int main()
{
Lazy_Callback lc(print_int, 5);
lc.call();
}
If the callback can be templated then you can use std::tuple
to store your arguments:
#include <tuple>
#include <iostream>
template <typename F, typename ...Args>
class Lazy_Callback
{
public:
template <typename ...Ts>
Lazy_Callback(F f, Ts && ...ts)
: _f(f), _args(ts...)
{ }
void call() const
{
return std::apply(_f, _args);
}
protected:
private:
F _f;
std::tuple<Args...> _args;
};
template <typename F, typename ...Ts>
Lazy_Callback<F, std::decay_t<Ts>...> make_callback(F && f, Ts && ...ts)
{
return { std::forward<F>(f), std::forward<Ts>(ts)... };
}
void print_int(int x)
{
std::cout << "x = " << x << "\n";
}
int main()
{
auto lc = make_callback(print_int, 5);
lc.call();
}