I hope this is what you were trying to achieve:
#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;
}
In my implementation connect
expects the actual argument types as template parameters. The connect
function returns an std::function
that expects arguments with ARGS...
types.
connect has two parameters:
- one for the object that has a variadic function (
object
).
- one for the member function pointer that points to the variadic function we would like to call (
funPtr
).
We cannot use std::bind
in the implementation (we could, but it would involve a lot of boilerplate to add as many std::placeholders
as we need based on the ARGS
).
So I introduce a lambda instead, that expects the actual ARGS
typed arguments. We can return the lambda as an std::function
and we are good to go.
https://godbolt.org/z/7cx3rcYh8
I created a version that can print out the variadic list as well:
https://godbolt.org/z/nMxj7Wh9j
Args...
? – Coheir