mlpack 3.4.2
sfinae_utility.hpp
Go to the documentation of this file.
1
15#ifndef MLPACK_CORE_SFINAE_UTILITY
16#define MLPACK_CORE_SFINAE_UTILITY
17
18#include <type_traits>
19#include <cstring>
20
21namespace mlpack {
22namespace sfinae {
23
24/*
25 * MethodFormDetector is a tool that helps to find out whether a given class has
26 * a method of the requested form. For that purpose MethodFormDetector defines
27 * an operator() that accepts a class member pointer for the given class. If the
28 * operator()(&Class::Method) call can be compiled, then the given class has a
29 * method of the requested form. For any provided AdditionalArgsCount, the check
30 * succeeds only if the given class has exactly one method of the requested form
31 * with AdditionalArgsCount additional arguments.
32 *
33 * The tool is dedicated to be used in type functions (structs) generated by the
34 * macro HAS_METHOD_FORM.
35 *
36 * @tparam MethodForm A template class member pointer type to a method of the
37 * form to look for.
38 * @tparam Class A class in which a method of the requested form should be
39 * looked for.
40 * @tparam AdditionalArgsCount A number of additional arguments.
41 */
42template<typename Class,
43 template<typename...> class MethodForm,
44 size_t AdditionalArgsCount>
46
47template<typename Class, template<typename...> class MethodForm>
48struct MethodFormDetector<Class, MethodForm, 0>
49{
50 void operator()(MethodForm<Class>);
51};
52
53template<typename Class, template<typename...> class MethodForm>
54struct MethodFormDetector<Class, MethodForm, 1>
55{
56 template<class T1>
57 void operator()(MethodForm<Class, T1>);
58};
59
60template<typename Class, template<typename...> class MethodForm>
61struct MethodFormDetector<Class, MethodForm, 2>
62{
63 template<class T1, class T2>
64 void operator()(MethodForm<Class, T1, T2>);
65};
66
67template<typename Class, template<typename...> class MethodForm>
68struct MethodFormDetector<Class, MethodForm, 3>
69{
70 template<class T1, class T2, class T3>
71 void operator()(MethodForm<Class, T1, T2, T3>);
72};
73
74template<typename Class, template<typename...> class MethodForm>
75struct MethodFormDetector<Class, MethodForm, 4>
76{
77 template<class T1, class T2, class T3, class T4>
78 void operator()(MethodForm<Class, T1, T2, T3, T4>);
79};
80
81template<typename Class, template<typename...> class MethodForm>
82struct MethodFormDetector<Class, MethodForm, 5>
83{
84 template<class T1, class T2, class T3, class T4, class T5>
85 void operator()(MethodForm<Class, T1, T2, T3, T4, T5>);
86};
87
88template<typename Class, template<typename...> class MethodForm>
89struct MethodFormDetector<Class, MethodForm, 6>
90{
91 template<class T1, class T2, class T3, class T4, class T5, class T6>
92 void operator()(MethodForm<Class, T1, T2, T3, T4, T5, T6>);
93};
94
95template<typename Class, template<typename...> class MethodForm>
96struct MethodFormDetector<Class, MethodForm, 7>
97{
98 template<class T1, class T2, class T3, class T4, class T5, class T6, class T7>
99 void operator()(MethodForm<Class, T1, T2, T3, T4, T5, T6, T7>);
100};
101
103template<typename U, U> struct SigCheck : std::true_type {};
104
105} // namespace sfinae
106} // namespace mlpack
107
108
109
110/*
111 * Constructs a template supporting the SFINAE pattern.
112 *
113 * This macro generates a template struct that is useful for enabling/disabling
114 * a method if the template class passed in contains a member function matching
115 * a given signature with a specified name.
116 *
117 * The generated struct should be used in conjunction with std::enable_if_t.
118 *
119 * For general references, see:
120 * http://stackoverflow.com/a/264088/391618
121 *
122 * For an mlpack specific use case, see /mlpack/core/util/prefixedoutstream.hpp
123 * and /mlpack/core/util/prefixedoutstream_impl.hpp
124 *
125 * @param NAME the name of the struct to construct. For example: HasToString
126 * @param FUNC the name of the function to check for. For example: ToString
127 */
128#define HAS_MEM_FUNC(FUNC, NAME) \
129template<typename T, typename sig, typename = std::true_type> \
130struct NAME : std::false_type {}; \
131 \
132template<typename T, typename sig> \
133struct NAME \
134< \
135 T, \
136 sig, \
137 std::integral_constant<bool, mlpack::sfinae::SigCheck<sig, &T::FUNC>::value> \
138> : std::true_type {};
139
143#define HAS_METHOD_FORM_BASE(METHOD, NAME, MAXN) \
144template<typename Class, \
145 template<typename...> class MF /* MethodForm */, \
146 size_t MinN = 0 /* MinNumberOfAdditionalArgs */> \
147struct NAME \
148{ \
149 /* Making a short alias for MethodFormDetector */ \
150 template<typename C, template<typename...> class MethodForm, int N> \
151 using MFD = mlpack::sfinae::MethodFormDetector<C, MethodForm, N>; \
152 \
153 template<size_t N> \
154 struct WithNAdditionalArgs \
155 { \
156 using yes = char[1]; \
157 using no = char[2]; \
158 \
159 template<typename T, typename ResultType> \
160 using EnableIfVoid = \
161 typename std::enable_if<std::is_void<T>::value, ResultType>::type; \
162 \
163 template<typename C> \
164 static EnableIfVoid<decltype(MFD<C, MF, N>()(&C::METHOD)), yes&> chk(int); \
165 template<typename> \
166 static no& chk(...); \
167 \
168 static const bool value = sizeof(chk<Class>(0)) == sizeof(yes); \
169 }; \
170 \
171 template<size_t N> \
172 struct WithGreaterOrEqualNumberOfAdditionalArgs \
173 { \
174 using type = typename std::conditional< \
175 WithNAdditionalArgs<N>::value, \
176 std::true_type, \
177 typename std::conditional< \
178 N < MAXN, \
179 WithGreaterOrEqualNumberOfAdditionalArgs<N + 1>, \
180 std::false_type>::type>::type; \
181 static const bool value = type::value; \
182 }; \
183 \
184 static const bool value = \
185 WithGreaterOrEqualNumberOfAdditionalArgs<MinN>::value; \
186};
187
201#define HAS_ANY_METHOD_FORM(FUNC, NAME) \
202template <typename T> \
203struct NAME \
204{ \
205 template <typename Q = T> \
206 static typename \
207 std::enable_if<std::is_member_function_pointer<decltype(&Q::FUNC)>::value, \
208 int>::type \
209 f(int) { return 1;} \
210 \
211 template <typename Q = T> \
212 static char f(char) { return 0; } \
213 \
214 static const bool value = sizeof(f<T>(0)) != sizeof(char); \
215};
216/*
217 * A macro that can be used for passing arguments containing commas to other
218 * macros.
219 */
220#define SINGLE_ARG(...) __VA_ARGS__
221
252#define HAS_METHOD_FORM(METHOD, NAME) \
253 HAS_METHOD_FORM_BASE(SINGLE_ARG(METHOD), SINGLE_ARG(NAME), 7)
254
285#define HAS_EXACT_METHOD_FORM(METHOD, NAME) \
286 HAS_METHOD_FORM_BASE(SINGLE_ARG(METHOD), SINGLE_ARG(NAME), 0)
287
321#endif
Linear algebra utility functions, generally performed on matrices or vectors.
Definition: cv.hpp:1
void operator()(MethodForm< Class, T1, T2, T3 >)
void operator()(MethodForm< Class, T1, T2, T3, T4 >)
void operator()(MethodForm< Class, T1, T2, T3, T4, T5 >)
void operator()(MethodForm< Class, T1, T2, T3, T4, T5, T6 >)
void operator()(MethodForm< Class, T1, T2, T3, T4, T5, T6, T7 >)
Utility struct for checking signatures.