Другое решение в случае ровно одной подписи.
Другое ... ну ... почти то же самое решение ecatmur, но основанное на функции шаблона, для вывода типов вместо класса шаблона.
Все, что вам нужно, это объявленная функция две объявленные функции, которые определяют типы (и возвращают тот же тип возврата, что и operator()
; вы можете также разработать другую функцию для возврата, например, std::tuple<Args...>
, если вам нужно извлечь Args...
типов)
template <typename T, typename R, typename ... Args>
R deducer (R(T::*)(Args...) const);
template <typename T, typename R, typename ... Args>
R deducer (R(T::*)(Args...));
и using
(небольшой decltype()
бред) для извлечения R
типа
template <typename T>
using RetType = decltype(deducer(std::declval<decltype(&T::operator())>()));
Ниже приведен полный пример C ++ 11
#include <utility>
struct A
{
long operator() (int, char, short)
{ return 0l; }
};
template <typename T, typename R, typename ... Args>
R deducer (R(T::*)(Args...) const);
template <typename T, typename R, typename ... Args>
R deducer (R(T::*)(Args...));
template <typename T>
using RetType = decltype(deducer(std::declval<decltype(&T::operator())>()));
int main ()
{
auto f = [](int& x) { return x++; };
static_assert( std::is_same<RetType<A>, long>::value, "!" );
static_assert( std::is_same<RetType<decltype(f)>, int>::value, "!" );
}
Если вы также хотите управлять volatile
операторами, вы должны добавить два других deducer()
template <typename T, typename R, typename ... Args>
R deducer (R(T::*)(Args...) volatile const);
template <typename T, typename R, typename ... Args>
R deducer (R(T::*)(Args...) volatile);