text: #ifndef _CPPUTIL_BASIC_HEADER_FUNCTION_TRAITS_H_
  #define _CPPUTIL_BASIC_HEADER_FUNCTION_TRAITS_H_
  
  #include <tuple>
  
  // src
  // https://stackoverflow.com/questions/7943525/is-it-possible-to-figure-out-the-parameter-type-and-return-type-of-a-lambda
  // kennytm
  
  namespace CppUtil {
  	namespace Basic {
  		template<typename T>
  		struct FunctionTraits;
  
  		template <typename T>
  		struct FunctionTraitsLambda
  			: public FunctionTraits<decltype(&T::operator())>
  		{};
  		// For generic types, directly use the result of the signature of its 'operator()'
  
  		template <typename ClassType, typename ReturnType, typename... Args>
  		struct FunctionTraits<ReturnType(ClassType::*)(Args...) const>
  			// we specialize for pointers to member function
  		{
  			enum { arity = sizeof...(Args) };
  			// arity is the number of arguments.
  
  			typedef ReturnType result_type;
  
  			typedef ClassType class_type;
  
  			template <size_t i>
  			struct arg
  			{
  				typedef typename std::tuple_element<i, std::tuple<Args...>>::type type;
  				// the i-th argument is equivalent to the i-th tuple element of a tuple
  				// composed of those arguments.
  			};
  		};
  
  		template <typename ReturnType, typename... Args>
  		struct FunctionTraits<ReturnType(Args...)>
  			// we specialize for pointers to member function
  		{
  			enum { arity = sizeof...(Args) };
  			// arity is the number of arguments.
  
  			typedef ReturnType result_type;
  
  			template <size_t i>
  			struct arg
  			{
  				typedef typename std::tuple_element<i, std::tuple<Args...>>::type type;
  				// the i-th argument is equivalent to the i-th tuple element of a tuple
  				// composed of those arguments.
  			};
  		};
  
  		template<typename T>
  		using RetT = typename FunctionTraits<T>::result_type;
  	}
  }
  
  
  #endif//!_CPPUTIL_BASIC_HEADER_FUNCTION_TRAITS_H_
  