以可变参数方式绑定成员函数

binding member functions in a variadic fashion

本文关键字:绑定 成员 函数 方式 参数 变参      更新时间:2023-10-16

我有一个参数数量可变的成员函数,存储在一个std::function中,我想绑定实例并获取一个独立的函数对象。

template <class T, class R, class... Args>
void connect(const T& t, std::function<R(const T&, Args...)> f) {
  std::function<R(Args...)> = /* bind the instance c into the function? */
}
// ...
Class c;
connect(c, &Class::foo);

对于固定数量的参数,我会使用 std::bind ,但我看不出如何为可变参数执行此操作。

我希望这就是您要实现的目标:

#include <iostream>
#include <cstdarg>
#include <functional>
class Class {
  public:
    void foo(...)
    {
        std::cout << "foo" << std::endl;
    } 
};
template <typename RES_T>
using ClassVarMemFunT = RES_T (Class::*)(...);
// Without typedef:
// template <class... ARGS, class CLASS_T, class RES_T>
// std::function<RES_T(ARGS...)> connect(CLASS_T& object, RES_T (CLASS_T::*funPtr)(...)) 
template <typename... ARGS, typename CLASS_T, typename RES_T>
std::function<RES_T(ARGS...)> connect(CLASS_T& object, ClassVarMemFunT<RES_T> funPtr)
{
    std::function<RES_T(ARGS...)> resultFun = [&object, funPtr](ARGS&&... args) -> RES_T { 
        return (object.*funPtr)(std::forward<ARGS>(args)...);
    };
    return resultFun;
}
int main() {
    Class c;
    auto funPtr1 = connect<int, float>(c, &Class::foo);
    funPtr1(10, 2.f);
    auto funPtr2 = connect<double, float, int>(c, &Class::foo);
    funPtr2(2., 2.f, 10);
    return 0;
}

在我的实现中,connect期望实际的参数类型作为模板参数。connect 函数返回一个需要具有ARGS...类型的参数的std::function

连接有两个参数:

  • 一个用于具有可变参数函数的对象(object)。
  • 一个用于成员函数指针,指向我们要调用的可变参数函数 (funPtr )。

我们不能在实现中使用std::bind(我们可以,但根据ARGS添加尽可能多的std::placeholders会涉及大量样板文件)。

因此,我引入了一个 lambda,它需要实际的ARGS类型参数。我们可以将 lambda 作为std::function返回,我们很好。

https://godbolt.org/z/7cx3rcYh8

我创建了一个可以打印出可变参数列表的版本:

https://godbolt.org/z/nMxj7Wh9j