Skip to content

Instantly share code, notes, and snippets.

@juxeii
Last active December 31, 2020 11:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save juxeii/dc2eb600c32a8461bc0a278687816189 to your computer and use it in GitHub Desktop.
Save juxeii/dc2eb600c32a8461bc0a278687816189 to your computer and use it in GitHub Desktop.
Blog post for CallableTraits
template <typename T>
using AsFunction = decltype(std::function{std::declval<T>()});
#if defined(__GNUC__) || defined(__GNUG__)
// CTAD bug in gcc, see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98077
#define AS_FUNCTION(T) decltype(std::function{std::declval<T>()})
#else
#define AS_FUNCTION(T) AsFunction<T>
#endif
template <typename T, typename = void>
struct is_callable : std::false_type
{
};
template <typename T>
struct is_callable<T, std::void_t<AS_FUNCTION(T)>> : std::true_type
{
};
template <typename T>
inline constexpr auto is_callable_v = is_callable<T>::value;
static_assert(!is_callable_v<int>);
auto l = []{};
static_assert(is_callable_v<decltype(l)>);
template <typename T>
struct function_components
{
};
template <typename R, typename... Args>
struct function_components<std::function<R(Args...)>>
{
using type = std::tuple<R(Args...), R, std::tuple<std::decay_t<Args>...>>;
};
template <typename T>
using function_components_t = typename function_components<T>::type;
template <typename T, auto I>
using get_function_component_t = std::tuple_element_t<I, function_components_t<T>>;
template <typename T>
using function_signature_t = get_function_component_t<T, 0>;
template <typename T>
using function_result_t = get_function_component_t<T, 1>;
template <typename T>
using function_arguments_t = get_function_component_t<T, 2>;
template <typename T>
struct callable_to_function
{
static_assert(is_callable_v<T>);
using type = AS_FUNCTION(T);
};
template <typename T>
using callable_to_function_t = typename callable_to_function<T>::type;
template <typename T>
struct callable_result
{
using type = function_result_t<callable_to_function_t<T>>;
};
template <typename T>
using callable_result_t = typename callable_result<T>::type;
template <typename T>
struct callable_arguments
{
using type = function_arguments_t<callable_to_function_t<T>>;
};
template <typename T>
using callable_arguments_t = typename callable_arguments<T>::type;
auto someFunc()
{
return 42;
}
using R = callable_result_t<decltype(someFunc)>;
static_assert(std::is_same_v<R, int>);
template <typename T>
struct callable_arguments
{
using type = function_arguments_t<callable_to_function_t<T>>;
};
template <typename T>
using callable_arguments_t = typename callable_arguments<T>::type;
auto sum(int x, int y)
{
return x+y;
}
using R = callable_arguments_t<decltype(sum)>;
static_assert(std::is_same_v<R, std::tuple<int, int>>);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment