是否可以创建一个独立的模板函数,它具有模板参数auto MEMFN
(成员函数指针),并且具有与MEMFN相同的返回和参数类型?
所以,如果MEMFN的类型是
RETURN (OBJECT::*)(PARAMETERS...)
然后所需的功能是:
template <auto MEMFN>
RETURN foo(OBJECT &, PARAMETERS...);
我的问题是如何从PARAMETERS...
中提取MEMFN's type
(RETURN
和OBJECT
很容易做到。)
所以我可以像这样调用这个函数:
Object o;
foo<&Object::func>(o, <parameters>...);
至于来自上午的请求,这是一个从实际代码中删除的示例:
#include <utility>
template <typename RETURN, typename OBJECT, typename ...PARAMETERS>
struct Wrapper {
template <RETURN (OBJECT::*MEMFN)(PARAMETERS...)>
RETURN foo(PARAMETERS... parameters) {
// do whatever with MEMFN, parameters, etc. here, not part of the problem
}
};
struct Object {
template <auto MEMFN, typename RETURN, typename OBJECT, typename ...PARAMETERS>
RETURN call(OBJECT &&object, PARAMETERS &&...parameters) {
// here, MEMFN parameters and PARAMETERS must be the same
// Wrapper actually not created here, it is accessed by other means
Wrapper<RETURN, typename std::decay<OBJECT>::type, PARAMETERS...> w;
return w.template foo<MEMFN>(std::forward<PARAMETERS>(parameters)...);
}
};
struct Foo {
void fn(int);
};
int main() {
Object o;
Foo f;
o.call<&Foo::fn, void, Foo &, int>(f, 42);
// this is wanted instead:
// o.call<&Foo::fn>(f, 42);
}
答案 0 :(得分:3)
是的,我们可以:
template <auto MemFn>
struct fooHelper;
template <typename Ret, typename Obj, typename ... Args, Ret (Obj::*MemFn)(Args...)>
struct fooHelper<MemFn>
{
static Ret call(Obj& obj, Args... args) {
return (obj.*MemFn)(args...);
}
};
template <auto MemFn, typename ... Args>
auto foo(Args ... args)
{
return fooHelper<MemFn>::call(args...);
}
定义foo
的另一种不引入全新参数包的方法是:
template <auto MemFn>
auto& foo = fooHelper<MemFn>::call;
使用示例:
#include <iostream>
struct moo
{
int doit (int x, int y) { return x + y; }
};
int main()
{
moo m;
std::cout << foo<&moo::doit>(m, 1, 2) << "\n";
}
(为简单起见省略了完美转发)
答案 1 :(得分:1)
如果您放松对独立的要求,可以执行以下操作:
#include <iostream>
template <auto MEMFN, class = decltype(MEMFN)>
struct S;
template <auto MEMFN, class Ret, class T, class... Args>
struct S<MEMFN, Ret (T::*)(Args...)> {
static Ret foo(T &o, Args... args) {
(o.*MEMFN)(args...);
}
};
struct A {
void foo(int a, int b) {
std::cout << a << " " << b << std::endl;
}
};
int main() {
A a;
S<&A::foo>::foo(a, 1, 2);
}
如果不是,那么你必须耐心为每个可能数量的参数创建一个函数重载:
#include <type_traits>
#include <tuple>
#include <iostream>
template <class, std::size_t>
struct DeduceParam;
template <class Ret, class T, class... Args, std::size_t N>
struct DeduceParam<Ret (T::*)(Args...), N> {
using type = std::tuple_element_t<N, std::tuple<Args...>>;
};
template <class>
struct DeduceResultAndType;
template <class Ret, class T, class... Args>
struct DeduceResultAndType<Ret (T::*)(Args...)> {
using result = Ret;
using type = T;
static constexpr decltype(sizeof(T)) size = sizeof...(Args);
};
template <auto MEMFN, class DRAT = DeduceResultAndType<decltype(MEMFN)>, std::enable_if_t<DRAT::size == 1>* = nullptr>
typename DRAT::result foo(typename DRAT::type o, typename DeduceParam<decltype(MEMFN), 0>::type param1) {
}
template <auto MEMFN, class DRAT = DeduceResultAndType<decltype(MEMFN)>, std::enable_if_t<DRAT::size == 2>* = nullptr>
typename DRAT::result foo(typename DRAT::type o, typename DeduceParam<decltype(MEMFN), 0>::type param1,
typename DeduceParam<decltype(MEMFN), 1>::type param2) {
}
struct A {
void foo(int a, int b) {
std::cout << a << " " << b << std::endl;
}
};
int main() {
A a;
foo<&A::foo>(a, 1, 2);
}