Я почти уверен, int (G::*)()
это указатель на функцию ...?Чего мне не хватает?
Не совсем: int (G::*)()
- указатель на нестатический метод.Это не совсем то же самое, и для его вызова требуется немного другой синтаксис.
Итак, вместо
return (t->h)(args...);
вы должны добавить *
и вызвать h()
какследует
return (t->*h)(args...);
// ........^ add this *
decltype()
также неправильно.Если вы можете использовать хотя бы C ++ 14, вы можете избежать этого и просто использовать auto
в качестве возвращаемого типа
template <typename T, typename F, typename ...Args>
auto f (F h, Args&&... args) {
T* t = new T();
return (t->*h)(args...);
}
В противном случае, если вы должны использовать C ++ 11, вы можете включить <utility>
и используйте std::declval()
следующим образом
template <typename T, typename F, typename ...Args>
auto f(F h, Args&&... args) -> decltype((std::declval<T*>()->*h)(args...)) {
T* t = new T(); // .................^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
return (t->*h)(args...);
}
Но есть и другой способ написать вашу f()
функцию: определить возвращаемый тип (избегая, таким образом, auto
, decltype()
и std::declval()
) и аргументы h()
Вы можете написать f()
следующим образом
template<typename R, typename T, typename ... As1, typename ... As2>
R f(R(T::*h)(As1...), As2 && ... args) {
T* t = new T();
return (t->*h)(args...);
}
, и вы избежите явного вызова типа G
, вызывающего его
int k = f(&G::g);
// .....^^^^^^^^ no more explicit <G> needed
потому что тип шаблона T
выводится из аргумента &G::g
.