Skip to content

Instantly share code, notes, and snippets.

@janderudder
Last active September 7, 2023 18:17
Show Gist options
  • Save janderudder/7e32fded5faeb71f924fd9920932b589 to your computer and use it in GitHub Desktop.
Save janderudder/7e32fded5faeb71f924fd9920932b589 to your computer and use it in GitHub Desktop.
Get argument and return type of function or callable object.
#ifndef CALLABLE_TRAITS_HPP_INCLUDED
#define CALLABLE_TRAITS_HPP_INCLUDED
#include <type_traits>
// synopsis
////////////////////////////////////////////////////////////////////////////////
template <typename>
struct callable_traits;
template <typename Fn>
constexpr bool is_function();
////////////////////////////////////////////////////////////////////////////////
namespace detail
{
template <typename...>
struct type_list;
template <>
struct type_list<>
{
using type = void;
using next = type_list<void>;
};
template <typename Head>
struct type_list<Head> {
using type = Head;
using next = type_list<void>;
};
template <typename Head, typename...Tail>
struct type_list<Head, Tail...> {
using type = Head;
using next = type_list<Tail...>;
};
} // detail
template <typename>
struct callable_traits;
template <typename Functor>
struct callable_traits
{
private: using Fr = std::remove_pointer_t<std::remove_cvref_t<Functor>>;
public:
using return_type = callable_traits<decltype(&Fr::operator())>::return_type;
using argument = callable_traits<decltype(&Fr::operator())>::argument;
};
template <typename Ret, typename... Args>
struct callable_traits<Ret(Args...)>
{
using return_type = Ret;
using argument = detail::type_list<Args...>;
};
template <typename Ret, typename... Args>
struct callable_traits<Ret(Args...) noexcept>
{
using return_type = Ret;
using argument = detail::type_list<Args...>;
};
template <typename Ret, typename... Args>
struct callable_traits<Ret(&)(Args...)>
{
using return_type = Ret;
using argument = detail::type_list<Args...>;
};
template <typename Ret, typename... Args>
struct callable_traits<Ret(&)(Args...) noexcept>
{
using return_type = Ret;
using argument = detail::type_list<Args...>;
};
template <typename Ret, typename... Args>
struct callable_traits<Ret(*)(Args...)>
{
using return_type = Ret;
using argument = detail::type_list<Args...>;
};
template <typename Ret, typename... Args>
struct callable_traits<Ret(*)(Args...) noexcept>
{
using return_type = Ret;
using argument = detail::type_list<Args...>;
};
template <typename Callable, typename Ret, typename... Args>
struct callable_traits<Ret (Callable::*)(Args...) const>
{
using return_type = Ret;
using argument = detail::type_list<Args...>;
};
template <typename Callable, typename Ret, typename... Args>
struct callable_traits<Ret (Callable::*)(Args...) const noexcept>
{
using return_type = Ret;
using argument = detail::type_list<Args...>;
};
template <typename Callable, typename Ret, typename ...Args>
struct callable_traits<Ret (Callable::*)(Args...)>
{
using return_type = Ret;
using argument = detail::type_list<Args...>;
};
template <typename Callable, typename Ret, typename ...Args>
struct callable_traits<Ret (Callable::*)(Args...) noexcept>
{
using return_type = Ret;
using argument = detail::type_list<Args...>;
};
template <typename Fn>
constexpr bool is_function()
{
return std::is_function_v<std::remove_pointer_t<std::remove_cvref_t<Fn>>>;
}
#endif // CALLABLE_TRAITS_HPP_INCLUDED
/*
launch with ./example | c++filt -t
*/
#include "callable_traits.hpp"
#include <functional>
#include <iostream>
#include <string>
#include <string_view>
#include <typeinfo>
template <typename Callable>
void displayTypes(Callable&&)
{
std::cout <<"ret: "<< typeid(typename callable_traits<Callable>::return_type).name() <<" | ";
std::cout <<"arg: "<< typeid(typename callable_traits<Callable>::argument::type).name() <<"\n";
}
struct Functor
{
std::string_view operator()() const { return "hello"; }
};
auto fn(short, char) { return 0; }
int main()
{
using namespace std;
auto constexpr lambda = [](double){};
displayTypes(lambda);
double d = 1.0;
auto const lambdaCapture = [&d](double f){ return (float)(d += f); };
displayTypes(lambdaCapture);
Functor functor;
displayTypes(functor);
Functor const cFunctor;
displayTypes(cFunctor);
displayTypes(fn);
displayTypes(&fn);
std::function<void(double)> fl1 {lambda};
std::function<float(double)> fl2 {lambdaCapture};
std::function<std::string_view()> fl3 {functor};
std::function<int(short,char)> fl4 {fn};
displayTypes(fl1);
displayTypes(fl2);
displayTypes(fl3);
displayTypes(fl4);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment