|
#pragma once |
|
|
|
#include <tuple> |
|
|
|
|
|
|
|
|
|
template <typename T> |
|
struct function_traits : public function_traits<decltype(&T::operator())> { |
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template <typename ClassType, typename T> |
|
struct function_traits<T ClassType::*> : public function_traits<T> { |
|
}; |
|
|
|
|
|
template <typename ClassType, typename ReturnType, typename... Args> |
|
struct function_traits<ReturnType(ClassType::*)(Args...) const> : public function_traits<ReturnType(Args...)> { |
|
}; |
|
|
|
|
|
template <typename T> |
|
struct function_traits<T&> : public function_traits<T> {}; |
|
template <typename T> |
|
struct function_traits<T*> : public function_traits<T> {}; |
|
|
|
|
|
template <typename ReturnType, typename... Args> |
|
struct function_traits<ReturnType(Args...)> { |
|
|
|
enum { arity = sizeof...(Args) }; |
|
|
|
typedef std::tuple<Args...> ArgsTuple; |
|
typedef ReturnType result_type; |
|
|
|
template <size_t i> |
|
struct arg |
|
{ |
|
typedef typename std::tuple_element<i, std::tuple<Args...>>::type type; |
|
|
|
|
|
}; |
|
}; |
|
|
|
template <typename T> |
|
struct nullary_function_traits { |
|
using traits = function_traits<T>; |
|
using result_type = typename traits::result_type; |
|
}; |
|
|
|
template <typename T> |
|
struct unary_function_traits { |
|
using traits = function_traits<T>; |
|
using result_type = typename traits::result_type; |
|
using arg1_t = typename traits::template arg<0>::type; |
|
}; |
|
|
|
template <typename T> |
|
struct binary_function_traits { |
|
using traits = function_traits<T>; |
|
using result_type = typename traits::result_type; |
|
using arg1_t = typename traits::template arg<0>::type; |
|
using arg2_t = typename traits::template arg<1>::type; |
|
}; |
|
|