如何合法地将函数指针转换为方法指针?
How to legally cast function pointer to method pointer?
我正在寻找 std::mem_fn
的对立面:将 函数指针 转换为 成员指针 (例如 void(*)(C*)
到 void(C::*)()
对于给定的 class C).
背景
我正在使用第 3 方库(比如 lib1.h)为另一个第 3 方库创建绑定(lib2.h ).
lib1.h 中的某些函数接收指向接受 Value
参数的方法的方法指针(也在 [=47= 中定义) ])。另一方面,lib2.h classes 不包含此类方法,因此我必须通过 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(并通过派生 classes of 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));
}
};
...可能还对要在包装对象上调用的成员函数和用于转换参数的函数进行参数化。
我正在寻找 std::mem_fn
的对立面:将 函数指针 转换为 成员指针 (例如 void(*)(C*)
到 void(C::*)()
对于给定的 class C).
背景
我正在使用第 3 方库(比如 lib1.h)为另一个第 3 方库创建绑定(lib2.h ).
lib1.h 中的某些函数接收指向接受 Value
参数的方法的方法指针(也在 [=47= 中定义) ])。另一方面,lib2.h classes 不包含此类方法,因此我必须通过 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(并通过派生 classes of 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));
}
};
...可能还对要在包装对象上调用的成员函数和用于转换参数的函数进行参数化。