Насколько я знаю, уловки с прямыми вызовами метода без контекста класса не определены стандартом.Кроме того, они строго не рекомендуются, потому что это зависит от компилятора, платформы и т. Д.
На самом деле, в зависимости от вашей задачи, вы можете использовать переменные шаблоны для вызова любого метода с любыми параметрами, например:
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.Но как насчет возвращения пустоты?Для этого нам нужна отдельная специализация шаблона:
// 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);