1#pragma once
2
3#include <tuple>
4
5// Modified from https://stackoverflow.com/questions/7943525/is-it-possible-to-figure-out-the-parameter-type-and-return-type-of-a-lambda
6
7// Fallback, anything with an operator()
8template <typename T>
9struct function_traits : public function_traits<decltype(&T::operator())> {
10};
11
12// Pointers to class members that are themselves functors.
13// For example, in the following code:
14// template <typename func_t>
15// struct S {
16// func_t f;
17// };
18// template <typename func_t>
19// S<func_t> make_s(func_t f) {
20// return S<func_t> { .f = f };
21// }
22//
23// auto s = make_s([] (int, float) -> double { /* ... */ });
24//
25// function_traits<decltype(&s::f)> traits;
26template <typename ClassType, typename T>
27struct function_traits<T ClassType::*> : public function_traits<T> {
28};
29
30// Const class member functions
31template <typename ClassType, typename ReturnType, typename... Args>
32struct function_traits<ReturnType(ClassType::*)(Args...) const> : public function_traits<ReturnType(Args...)> {
33};
34
35// Reference types
36template <typename T>
37struct function_traits<T&> : public function_traits<T> {};
38template <typename T>
39struct function_traits<T*> : public function_traits<T> {};
40
41// Free functions
42template <typename ReturnType, typename... Args>
43struct function_traits<ReturnType(Args...)> {
44 // arity is the number of arguments.
45 enum { arity = sizeof...(Args) };
46
47 typedef std::tuple<Args...> ArgsTuple;
48 typedef ReturnType result_type;
49
50 template <size_t i>
51 struct arg
52 {
53 typedef typename std::tuple_element<i, std::tuple<Args...>>::type type;
54 // the i-th argument is equivalent to the i-th tuple element of a tuple
55 // composed of those arguments.
56 };
57};
58
59template <typename T>
60struct nullary_function_traits {
61 using traits = function_traits<T>;
62 using result_type = typename traits::result_type;
63};
64
65template <typename T>
66struct unary_function_traits {
67 using traits = function_traits<T>;
68 using result_type = typename traits::result_type;
69 using arg1_t = typename traits::template arg<0>::type;
70};
71
72template <typename T>
73struct binary_function_traits {
74 using traits = function_traits<T>;
75 using result_type = typename traits::result_type;
76 using arg1_t = typename traits::template arg<0>::type;
77 using arg2_t = typename traits::template arg<1>::type;
78};
79
80
81// Traits for calling with c10::guts::invoke, where member_functions have a first argument of ClassType
82template <typename T>
83struct invoke_traits : public function_traits<T>{
84};
85
86template <typename T>
87struct invoke_traits<T&> : public invoke_traits<T>{
88};
89
90template <typename T>
91struct invoke_traits<T&&> : public invoke_traits<T>{
92};
93
94template <typename ClassType, typename ReturnType, typename... Args>
95struct invoke_traits<ReturnType(ClassType::*)(Args...)> :
96 public function_traits<ReturnType(ClassType&, Args...)> {
97};
98
99template <typename ClassType, typename ReturnType, typename... Args>
100struct invoke_traits<ReturnType(ClassType::*)(Args...) const> :
101 public function_traits<ReturnType(const ClassType&, Args...)> {
102};
103