Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
#include <type_traits>
#include <tuple>
#include <functional>
template <typename FType>
struct function_traits;
template <typename RType, typename... ArgTypes>
struct function_traits<RType(ArgTypes...)> {
using arity = std::integral_constant<size_t, sizeof...(ArgTypes)>;
using result_type = RType;
using arg_tuple = std::tuple<ArgTypes...>;
template <size_t Index>
using arg_type = typename std::tuple_element<Index, arg_tuple>::type;
};
namespace details {
template <typename T>
struct function_type_impl
: function_type_impl<decltype(&T::operator())>
{ };
template <typename RType, typename... ArgTypes>
struct function_type_impl<RType(ArgTypes...)> {
using type = RType(ArgTypes...);
};
template <typename RType, typename... ArgTypes>
struct function_type_impl<RType(*)(ArgTypes...)> {
using type = RType(ArgTypes...);
};
template <typename RType, typename... ArgTypes>
struct function_type_impl<std::function<RType(ArgTypes...)>> {
using type = RType(ArgTypes...);
};
template <typename T, typename RType, typename... ArgTypes>
struct function_type_impl<RType(T::*)(ArgTypes...)> {
using type = RType(ArgTypes...);
};
template <typename T, typename RType, typename... ArgTypes>
struct function_type_impl<RType(T::*)(ArgTypes...) const> {
using type = RType(ArgTypes...);
};
}
template <typename T>
struct function_type
: details::function_type_impl<typename std::remove_cv<typename std::remove_reference<T>::type>::type>
{ };
// --- shortcuts ---
template <typename FType>
using function_type_traits_t = function_traits<typename function_type<FType>::type>;
template <typename FType>
constexpr auto function_arity_val = function_type_traits_t<FType>::arity::value;
template <typename FType>
using function_arg_tuple_t = typename function_type_traits_t<FType>::arg_tuple;
struct meow {
void f(int, char, float) { }
};
template <typename FType>
void test() {
using FTypeTraits = function_traits<FType>;
static_assert(typename FTypeTraits::arity() == 3, "fail");
static_assert(std::is_same<typename FTypeTraits::result_type, void>(), "fail");
static_assert(std::is_same<typename FTypeTraits::template arg_type<0>, int>(), "fail");
static_assert(std::is_same<typename FTypeTraits::template arg_type<1>, char>(), "fail");
static_assert(std::is_same<typename FTypeTraits::template arg_type<2>, float>(), "fail");
}
void test1() {
using FType = void(int, char, float);
test<FType>();
}
void test2() {
using FType = function_type<decltype(&meow::f)>::type;
test<FType>();
}
void test3() {
using FType = function_type<void(* const volatile &)(int, char, float)>::type;
test<FType>();
}
void test4() {
using FType = function_type<std::function<void(int, char, float)>>::type;
test<FType>();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.