Created
September 10, 2022 14:40
-
-
Save b1ackviking/6a73add2565b1af227aa5c4dc8daa988 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <cstddef> | |
#include <tuple> | |
template<class F> | |
struct function_traits; | |
// function pointer | |
template<class R, class... Args> | |
struct function_traits<R(*)(Args...)> : public function_traits<R(Args...)> | |
{}; | |
template<class R, class... Args> | |
struct function_traits<R(Args...)> | |
{ | |
using return_type = R; | |
static constexpr std::size_t arity = sizeof...(Args); | |
template <std::size_t N> | |
struct argument | |
{ | |
static_assert(N < arity, "error: invalid parameter index."); | |
using type = typename std::tuple_element<N,std::tuple<Args...>>::type; | |
}; | |
}; | |
// member function pointer | |
template<class C, class R, class... Args> | |
struct function_traits<R(C::*)(Args...)> : public function_traits<R(C&,Args...)> | |
{}; | |
// const member function pointer | |
template<class C, class R, class... Args> | |
struct function_traits<R(C::*)(Args...) const> : public function_traits<R(C&,Args...)> | |
{}; | |
// member object pointer | |
template<class C, class R> | |
struct function_traits<R(C::*)> : public function_traits<R(C&)> | |
{}; | |
// functor | |
template<class F> | |
struct function_traits | |
{ | |
private: | |
using call_type = function_traits<decltype(&F::operator())>; | |
public: | |
using return_type = typename call_type::return_type; | |
static constexpr std::size_t arity = call_type::arity - 1; | |
template <std::size_t N> | |
struct argument | |
{ | |
static_assert(N < arity, "error: invalid parameter index."); | |
using type = typename call_type::template argument<N+1>::type; | |
}; | |
}; | |
template<class F> | |
struct function_traits<F&> : public function_traits<F> | |
{}; | |
template<class F> | |
struct function_traits<F&&> : public function_traits<F> | |
{}; | |
#include <type_traits> | |
static_assert(std::is_same_v<function_traits<int(*)(float, double)>::return_type, int>); | |
static_assert(std::is_same_v<function_traits<int(*)(float, double)>::argument<0>::type, float>); | |
static_assert(std::is_same_v<function_traits<int(*)(float, double)>::argument<1>::type, double>); | |
static_assert(function_traits<int(*)(float, double)>::arity == 2); | |
using lambda = decltype([](float, double) {return 0;}); | |
static_assert(std::is_same_v<function_traits<lambda>::return_type, int>); | |
static_assert(std::is_same_v<function_traits<lambda>::return_type, int>); | |
static_assert(std::is_same_v<function_traits<lambda>::argument<0>::type, float>); | |
static_assert(std::is_same_v<function_traits<lambda>::argument<1>::type, double>); | |
static_assert(function_traits<lambda>::arity == 2); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment