如果两个类都不是从另一个类派生或以任何方式关联的,则它以任何方式违反C ++标准(它的任何版本)从一个类方法重新解释_cast到一个完全不同的类方法指针,只要该指针直到被重新解释回正确的类对象才被取消引用?
在任何标准实现中,不同类方法指针的类型是否不同? (例如,也许一类是多态的,而另一类不是多态的)
这篇文章说,reinterpret_cast的用法遵循以下标准:https://stackoverflow.com/a/573345
这篇文章说,从方法指针到函数指针的转换是UB,这不是我正在做的,但是在理论上是相似的:https://stackoverflow.com/a/6908641
编辑:我需要运行时通用性,因为我要持有这些指针的向量,并且由于模板是在编译时求值的,因此效果不佳。我有点需要颠覆类型系统以持有通用指针,并知道当我将其强制转换回原始类型时,它将不会被破坏。
我要实现的伪代码:
// A type for Foo method pointer
typedef bool (Foo::*FOO_METHOD_PTR)( int some_arg );
// A generic method pointer type
class UnusedClass {};
typedef void (UnusedClass::*GENERIC_METHOD_PTR)( void );
// generically store a method from any class
GENERIC_METHOD_PTR generic_ptr = reinterpret_cast<GENERIC_METHOD_PTR>( &Foo::method );
// cast back to proper class
FOO_METHOD_PTR foo_ptr = reinterpret_cast<FOO_METHOD_PTR>( generic_ptr );
// macro to help call method pointers
#define CALL_METHOD(object,ptrToMethod) ((object).*(ptrToMethod))
// call
Foo foo;
CALL_METHOD(foo,foo_ptr)
答案 0 :(得分:2)
该标准确实可以保证您要求的行为:(C ++ 17 [expr.reinterpret.cast] / 10)
如果T1和T2都是函数类型或都是对象类型,则可以将“指向T1类型的X成员的指针”类型的prvalue显式转换为“指向T2类型的Y成员的指针”类型的prvalue。 。空成员指针值将转换为目标类型的空成员指针值。除以下情况外,未指定此转换的结果:
- 将类型为“指向成员函数的指针”的prvalue转换为指向成员函数类型的不同指针,然后再返回其原始类型将产生指向成员值的原始指针。
- [...]
是的,您可以将一个指向成员函数的指针reinterpret_cast
传递给另一个函数以进行存储,然后使用强制类型转换的逆函数来检索原始值。
当然,您不能尝试通过中间指向成员的指针来调用函数。
答案 1 :(得分:1)
据我所知,标准中未指定直接调用不带类上下文的方法的技巧。另外,也不建议使用它们,因为它取决于编译器,平台等。
实际上,根据您的任务,您可以使用可变参数模板来调用具有任何参数的任何方法,例如:
template<typename TClass, typename TResult, typename ... Type>
struct SmartCall {
// call for non-const class methods
static TResult Invoke(TClass* context, TResult (TClass::*method)(Type...), Type... args) {
return (context->*(method))(args ...);
}
// call for const class methods
static TResult Invoke(TClass* context, TResult (TClass::*method)(Type...) const, Type... args) {
return (context->*(method))(args ...);
}
};
很好,您可以将其用于任何返回void以外内容的类的const和非const方法调用。但是返回虚空呢?我们需要对其进行单独的模板专门化:
// SmartCall specialization for 'void' return type
template<typename TClass, typename ... Type>
struct SmartCall<TClass, void, Type...> {
static void Invoke(TClass* context, void (TClass::*method)(Type...), Type... args) {
(context->*(method))(args ...);
}
static void Invoke(TClass* context, void(TClass::*method)(Type...) const, Type... args) {
return (context->*(method))(args ...);
}
};
用法示例:
std::string a = "Hello World";
// same as size = a.size();
size_t size = SmartCall<std::string, size_t>::Invoke(&a, &std::string::size);
// same as symbol_w_pos = a.find_first_of("W", 0);
size_t symbol_w_pos = SmartCall<std::string, size_t, const char*, const std::size_t>::Invoke(&a, &std::string::find_first_of, "W", 0);
// same as a.clear();
SmartCall<std::string, void>::Invoke(&a, &std::string::clear);