-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfunc.h
More file actions
153 lines (126 loc) · 4.18 KB
/
func.h
File metadata and controls
153 lines (126 loc) · 4.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
//
// Created by Makram Kamaleddine on 11/13/15.
//
#ifndef MY_MPL_FUNC_H
#define MY_MPL_FUNC_H
#include "inspect.h"
#include <utility>
namespace mpl {
// figure out the arity of a function f
// using recursion only
template<typename Ret, typename... Args>
struct arity_of;
template<typename Ret, typename Arg0, typename... Args>
struct arity_of<Ret(Arg0, Args...)>
{
static constexpr auto value = 1 + arity_of<Ret(Args...)>::value;
};
template<typename Ret, typename Arg>
struct arity_of<Ret(Arg)>
{
static constexpr auto value = 1;
};
template<typename Ret>
struct arity_of<Ret()>
{
static constexpr auto value = 0;
};
// dummy pattern
template<typename, typename, typename...>
struct returns;
// check the return type of a function against
// a given type.
template<typename T, typename Ret, typename... Args>
struct returns<T, Ret(Args...)>
{
static constexpr auto value = equal_types<T, Ret>::value;
};
// metafunction that gets the return type of the given
// function (or decltype(f), more correctly)
template<typename>
struct return_type;
template<typename Ret, typename... Args>
struct return_type<Ret(Args...)>
{
using type = Ret;
};
// check the argument types of a function against
// a given type
template<typename T, typename Ret, typename... Args>
struct args_have_type;
template<typename T, typename Ret, typename Arg0, typename... Args>
struct args_have_type<T, Ret(Arg0, Args...)>
{
static constexpr auto value = equal_types<T, Arg0>::value && args_have_type<T, Ret(Args...)>::value;
};
template<typename T, typename Ret, typename Arg>
struct args_have_type<T, Ret(Arg)>
{
static constexpr auto value = equal_types<T, Arg>::value;
};
// cases where we have no arguments and void as type to check
template<typename T, typename Ret>
struct args_have_type<T, Ret()>
{
static constexpr auto value = false;
};
template<typename Ret>
struct args_have_type<void, Ret()>
{
static constexpr auto value = true;
};
// a useful alias template if i can get it right
template<typename T, typename Ret, typename... Args>
using args_have_type_v = typename args_have_type<T, Ret(Args...)>::value;
// check that one of the arguments to the function
// is of the given type
template<typename T, typename Ret, typename... Args>
struct has_arg_type;
template<typename T, typename Ret, typename Arg0, typename... Args>
struct has_arg_type<T, Ret(Arg0, Args...)>
{
static constexpr auto value = equal_types<T, Arg0>::value ? true : has_arg_type<T, Ret(Args...)>::value;
};
template<typename T, typename Ret, typename Arg>
struct has_arg_type<T, Ret(Arg)>
{
static constexpr auto value = equal_types<T, Arg>::value;
};
template<typename T, typename Ret>
struct has_arg_type<T, Ret()>
{
static constexpr auto value = false;
};
template<typename Ret>
struct has_arg_type<void, Ret()>
{
static constexpr auto value = true;
};
// useful alias template
template<typename T, typename Ret, typename... Args>
using has_arg_type_v = typename has_arg_type<T, Ret(Args...)>::value;
// dummy template
template<typename Ret, typename... Args>
struct arithmetic_args;
// a template to determine whether the arguments
// of a function are all arithmetic types
template<typename Ret, typename Arg0, typename... Args>
struct arithmetic_args<Ret(Arg0, Args...)>
{
static constexpr auto value = std::is_arithmetic<Arg0>::value && arithmetic_args<Ret(Args...)>::value;
};
// end the recursion
template<typename Ret, typename Arg>
struct arithmetic_args<Ret(Arg)>
{
static constexpr auto value = std::is_arithmetic<Arg>::value;
};
// a function with no arguments has no arithmetic
// arguments (or is it vacuously true? no idea)
template<typename Ret>
struct arithmetic_args<Ret()>
{
static constexpr auto value = false;
};
}
#endif //MY_MPL_FUNC_H