I wrote this simple FunctionTraits structure that allows you to inspect function types at compile time, that is, to look “inside” a function and discover what arguments it takes and what it returns.
Here’s the full implementation:
#include <type_traits>
#include <tuple>
template<typename, typename = std::void_t<>>
struct FunctionTraits {};
template<typename Return, typename ...Args>
struct FunctionTraits<Return (*)(Args...)> {
using ReturnType = Return;
using ArgTypes = std::tuple<Args...>;
};
template<typename Return, typename Class, typename ...Args>
struct FunctionTraits<Return (Class::*)(Args...)> {
using ReturnType = Return;
using ArgTypes = std::tuple<Args...>;
};
template<typename Return, typename Class, typename ...Args>
struct FunctionTraits<Return (Class::*)(Args...) const> {
using ReturnType = Return;
using ArgTypes = std::tuple<Args...>;
};
template<typename F>
struct FunctionTraits<F, std::void_t<decltype(&F::operator())>> {
using ReturnType = typename FunctionTraits<decltype(&F::operator())>::ReturnType;
using ArgTypes = typename FunctionTraits<decltype(&F::operator())>::ArgTypes;
};
How It Works
Let’s break it down piece by piece.