Request Short Link
C++ 98
C++ 11
C++ 14
C++ 17
C++ 20
C++ 23
C++ 2c
for-loops as while-loops
array subscription
Show all implicit casts
Show all template parameters of a CallExpr
Use libc++
Transform std::initializer_list
Show noexcept internals
Show padding information
Show coroutine transformation
Show C++ to C transformation
Show object lifetime
Default
15
18
20
22
26
More
GitHub
Patreon
Issues
About
Policies
Examples
C++ Insights @ YouTube
Settings
Version
Need in-house C++ training? Learn more here
×
Made by
Andreas Fertig
Powered by
Flask
and
CodeMirror
Source:
#include <functional> #include <tuple> #include <type_traits> template <typename Args> struct TupleTrait; template <typename HeadT, typename... TailT> struct TupleTrait<std::tuple<HeadT, TailT...>> { using Head = HeadT; using Tail = std::tuple<TailT...>; static constexpr size_t count = 1 + sizeof...(TailT); template <size_t i> using Arg = decltype(std::get<i>(std::declval<std::tuple<HeadT, TailT...>>())); }; template <> struct TupleTrait<std::tuple<>> { using Tail = std::tuple<>; static constexpr size_t count = 0; }; template <typename Func, typename Enable = void> struct FunctionTrait; template <typename Ret, typename... Args> struct FunctionTrait<Ret (*)(Args...)> { using ReturnType = Ret; using Arguments = std::tuple<Args...>; }; template <typename C, typename Ret, typename... Args> struct FunctionTrait<Ret (C::*)(Args...)> : FunctionTrait<Ret (*)(C*, Args...)> {}; template <typename C, typename Ret, typename... Args> struct FunctionTrait<Ret (C::*)(Args...) const> : FunctionTrait<Ret (*)(C*, Args...)> {}; template <typename C, typename Ret, typename... Args> struct FunctionTrait<Ret (C::*)(Args...) noexcept> : FunctionTrait<Ret (*)(C*, Args...)> {}; template <typename C, typename Ret, typename... Args> struct FunctionTrait<Ret (C::*)(Args...) volatile> : FunctionTrait<Ret (*)(C*, Args...)> {}; template <typename C, typename Ret, typename... Args> struct FunctionTrait<Ret (C::*)(Args...) const noexcept> : FunctionTrait<Ret (*)(C*, Args...)> {}; template <typename C, typename Ret, typename... Args> struct FunctionTrait<Ret (C::*)(Args...) const volatile> : FunctionTrait<Ret (*)(C*, Args...)> {}; template <typename C, typename Ret, typename... Args> struct FunctionTrait<Ret (C::*)(Args...) volatile noexcept> : FunctionTrait<Ret (*)(C*, Args...)> { }; template <typename C, typename Ret, typename... Args> struct FunctionTrait<Ret (C::*)(Args...) const volatile noexcept> : FunctionTrait<Ret (*)(C*, Args...)> {}; // functor and lambda template <typename Functor> struct FunctionTrait<Functor, std::void_t<decltype(&Functor::operator())>> { private: using FunctorTrait = FunctionTrait<decltype(&Functor::operator())>; public: using ReturnType = typename FunctorTrait::ReturnType; using Arguments = typename TupleTrait<typename FunctorTrait::Arguments>::Tail; }; // decay: remove const, reference; function type to function pointer template <typename Func> struct FunctionTrait<Func, std::enable_if_t<!std::is_same_v<Func, std::decay_t<Func>>>> : FunctionTrait<std::decay_t<Func>> {}; // test static_assert(std::is_same_v<FunctionTrait<bool(int)>::ReturnType, bool>); auto lambda = [](int) -> bool { return true;}; static_assert(std::is_same_v<FunctionTrait<decltype(lambda)>::ReturnType, bool>); struct A { int hello(char); }; static_assert(std::is_same_v<FunctionTrait<decltype(&A::hello)>::ReturnType, int>);
Insight:
Console: