我正在寻找与std::mem_fn
相反的方法:将函数指针转换为成员指针的void(*)(C*)
到void(C::*)()
(。
背景
我正在使用第三方库(比如lib1.h(为另一个第三方图书馆(lib2.h(创建绑定
lib1.h中的一些函数接收方法指针,指向接受Value
参数的方法(也在libr1.h中定义(。另一方面,lib 2.h类不包含这样的方法,所以我必须通过lambda函数手动进行包装:
/* lib1.h (can't touch this) */
class Value;
class Property;
template <typename C>
struct ObjectWrap {
using Method = void(C::*)(Value);
static Property declare(std::string name, Method method);
};
/* lib2.h (can't touch this) */
struct Person {
void greet(std::string name);
};
/* bindings.cpp */
std::string value_to_std_string(Value v);
Property declarePersonGreet() {
return ObjectWrap<Person>::declare("greet",
/* ERROR */ [](Person* p, Value v) {
p->greet(value_to_std_string(v));
});
}
我很有信心,我没有滥用lib1.h的API(不幸的是,通过派生lib2.h类来实现这些方法不是一个选项(。因此,我觉得强制转换为方法指针是唯一的解决方案。
有什么合法的方法吗?如果可能的话,我想避免不明确的行为。
不,您不能执行这样的强制转换。即使你可以得到一个void(Person::*)(Value)
,你也不能使用它,因为Person
没有这样的方法。如果lib1期望一个具有成员函数void(C::)(Value)
的类型C
,那么就没有办法为这种类型C
提供相应的方法。您可以为Person
:编写一个包装器
struct Wrapper {
Person p;
void greet(Value v) {
p.greet(value_to_std_string(v));
}
};
Property declarePersonGreet() {
return ObjectWrap<Wrapper>::declare("greet",&Wrapper::greet);
}
如果你有很多类似于Person
的类,你可以把包装器做成一个模板:
template <typename T>
struct Wrapper {
T p;
void greet(Value v) {
p.greet(value_to_std_string(v));
}
};
也可能对要在包装对象上调用的成员函数和用于转换参数的函数进行参数化。