保存并传递给C ++中模板参数的函数列表

时间:2020-10-28 12:22:05

标签: c++ templates callback variadic-templates

我想保存模板参数列表并将其传递给函数。
std::thread一样,将参数传递给线程。参数类型是模板化的,参数计数不是静态的。

示例,它将如何工作:

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

或者我该如何实现:

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

有可能吗?
我该如何实施?

2 个答案:

答案 0 :(得分:4)

如果您不希望回调依赖于参数的类型,则必须使用某种类型的擦除。例如,您可以使用std::function中的<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();
}

如果可以将回调模板化,则可以使用std::tuple存储参数:

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

答案 1 :(得分:0)

您是否正在寻找类似std::bind的东西?这是一个简单的示例,您可能会扩展:

#include <iostream>
#include <functional>

template <typename T1, typename T2>
void printSum(const T1& a, const T2& b)
{
    std::cout << a + b << std::endl;
}

int main()
{
    const auto callback = std::bind(&printSum<int, int>, 1, 2);

    // ...
    
    callback();
}