如何使用元编程在c++中编写此函数



你想达到什么目标

我想将RetType ClassA::MemberFunc(Args...)转换为mem_fn(&ClassA::MemberFunc)但它就像一个函数为了避免为每个成员函数写lambda或函数

你得到了什么(包括错误信息)

no matching function for call to ‘regisAdd(std::_Mem_fn<int (ABC::*)(int, int)>)’

这是我的代码。

#include <functional>
#include <iostream>
using namespace std;
struct ABC {
int value;
int add(int a, int b) {
return a + b * value;
}
int other(int a) {
return a * value;
}
};
int doAdd(void* data, int a, int b) {
ABC* p = (ABC*)data;
return p->add(a, b);
}
typedef int (*TYPE_ADD)(void* data, int a, int b);
TYPE_ADD gAdd = nullptr;
void regisAdd(TYPE_ADD a) {
gAdd = a;
}
void callAdd() {
if (!gAdd) return;
ABC abc;
abc.value = 10;
cout << gAdd(&abc, 1, 2) << endl;
}
typedef int (*TYPE_OTHER)(void* data, int a);
TYPE_OTHER gOther = nullptr;
void regisOther(TYPE_OTHER a) {
gOther = a;
}
void callOther() {
if (!gOther) return;
ABC abc;
abc.value = 10;
cout << gOther(&abc, 12) << endl;
}
int main() {
regisAdd(doAdd);                               // this is GOOD
callAdd();                                     // call
regisAdd([](void* data, int a, int b) {        // < this is also GOOD
return static_cast<ABC*>(data)->add(a, b); // < GOOD
});                                            // < GOOD
callAdd();                                     // call
// how to write a general function work like mem_fn
// to avoid write doAdd and lambda for every function signatures
// regisAdd(mem_fn(&ABC::add));
// regisOther(mem_fn(&ABC::other));
// callAdd();
return 0;
}

据我所知,您想要这样的内容:

template <auto mem> // C++17, else <typename T, T mem>
struct mem_to_func;
template <typename C, typename Ret, typename ... Args,
Ret (C::*m)(Args...)>
struct mem_to_func<m>
{
static Ret func_ptr(C* c, Args... args)
{
return (c->*m)(std::forward<Args>(args)...);
}
static Ret func_ref(C& c, Args... args)
{
return (c.*m)(std::forward<Args>(args)...);
}
static Ret func_voidp(void* p, Args... args)
{
auto* c = static_cast<C*>(p);
return (c->*m)(std::forward<Args>(args)...);
}
};
template <typename C, typename Ret, typename ... Args,
Ret (C::*m)(Args...) const>
struct mem_to_func<m>
{
static Ret func(const C* c, Args... args)
{
return (c->*m)(std::forward<Args>(args)...);
}
static Ret func_ref(const C& c, Args... args)
{
return (c.*m)(std::forward<Args>(args)...);
}
static Ret func_voidp(const void* p, Args... args)
{
const auto* c = static_cast<const C*>(p);
return (c->*m)(std::forward<Args>(args)...);
}
};
// Others specializations for combination with
// - volatile,
// - reference to this,
// - and C-ellipsis... 

regisAdd(mem_to_func<&ABC::add>::func_voidp);