1 /*
2 Copyright Barrett Adair 2016-2017
3 Distributed under the Boost Software License, Version 1.0.
4 (See accompanying file LICENSE.md or copy at http ://boost.org/LICENSE_1_0.txt)
5 */
6
7 #include <type_traits>
8 #include <functional>
9 #include <utility>
10 #include <boost/callable_traits/is_invocable.hpp>
11 #include "test.hpp"
12
13 #ifdef BOOST_CLBL_TRTS_GCC_OLDER_THAN_4_9_2
14 //gcc < 4.9 doesn't like the invoke_case pattern used here
main()15 int main(){}
16 #else
17
18 template<typename T>
19 struct tag {
20 using type = T;
21 };
22
23 template<bool Expect, typename Ret, typename... Args>
24 struct invoke_case {
25 template<typename Callable>
operator ()invoke_case26 void operator()(tag<Callable>) const {
27
28 // when available, test parity with std implementation (c++2a breaks our expectations but we still match std impl)
29 #if defined(__cpp_lib_is_invocable) || __cplusplus >= 201707L
30 CT_ASSERT((std::is_invocable_r<Ret, Callable, Args...>() == boost::callable_traits::is_invocable_r<Ret, Callable, Args...>()));
31 # ifndef BOOST_CLBL_TRTS_DISABLE_VARIABLE_TEMPLATES
32 CT_ASSERT((std::is_invocable_r_v<Ret, Callable, Args...> == boost::callable_traits::is_invocable_r_v<Ret, Callable, Args...>));
33 # endif
34 #else
35 CT_ASSERT((Expect == boost::callable_traits::is_invocable_r<Ret, Callable, Args...>()));
36 # ifndef BOOST_CLBL_TRTS_DISABLE_VARIABLE_TEMPLATES
37 CT_ASSERT((Expect == boost::callable_traits::is_invocable_r_v<Ret, Callable, Args...>));
38 # endif
39 #endif
40
41 }
42 };
43
44 template<typename Callable, typename... InvokeCases>
run_tests()45 void run_tests() {
46 using ignored = int[];
47 ignored x {(InvokeCases{}(tag<Callable>{}),0)..., 0};
48 (void)x;
49 }
50
51 struct foo {};
52
main()53 int main() {
54
55 run_tests<void(foo::*)()
56 ,invoke_case<true, void, foo>
57 ,invoke_case<true, void, foo*>
58 ,invoke_case<true, void, foo&>
59 ,invoke_case<true, void, foo&&>
60 ,invoke_case<true, void, std::reference_wrapper<foo>>
61 ,invoke_case<false, int, foo>
62 ,invoke_case<false, int, foo*>
63 ,invoke_case<false, int, foo&>
64 ,invoke_case<false, int, foo&&>
65 ,invoke_case<false, int, std::reference_wrapper<foo>>
66 ,invoke_case<false, void, foo const>
67 ,invoke_case<false, void, foo const*>
68 ,invoke_case<false, void, foo const&>
69 ,invoke_case<false, void, foo const&&>
70 ,invoke_case<false, void, std::reference_wrapper<foo const>>
71 ,invoke_case<false, void, foo, int>
72 ,invoke_case<false, void, foo*, int>
73 ,invoke_case<false, void, foo&, int>
74 ,invoke_case<false, void, foo&&, int>
75 ,invoke_case<false, void, std::reference_wrapper<foo>, int>
76 ,invoke_case<false, int, foo const>
77 ,invoke_case<false, int, foo const*>
78 ,invoke_case<false, int, foo const&>
79 ,invoke_case<false, int, foo const&&>
80 ,invoke_case<false, int, std::reference_wrapper<foo const>>
81 ,invoke_case<false, int, foo, int>
82 ,invoke_case<false, int, foo*, int>
83 ,invoke_case<false, int, foo&, int>
84 ,invoke_case<false, int, foo&&, int>
85 ,invoke_case<false, int, std::reference_wrapper<foo>, int>
86 >();
87
88 run_tests<char(foo::*)()
89 ,invoke_case<true, void, foo>
90 ,invoke_case<true, void, foo*>
91 ,invoke_case<true, void, foo&>
92 ,invoke_case<true, void, foo&&>
93 ,invoke_case<true, void, std::reference_wrapper<foo>>
94 ,invoke_case<true, int, foo>
95 ,invoke_case<true, int, foo*>
96 ,invoke_case<true, int, foo&>
97 ,invoke_case<true, int, foo&&>
98 ,invoke_case<true, int, std::reference_wrapper<foo>>
99 >();
100
101 run_tests<void(foo::*)() LREF
102 ,invoke_case<false, void, foo>
103 ,invoke_case<true, void, foo*>
104 ,invoke_case<true, void, foo&>
105 ,invoke_case<false, int, foo*>
106 ,invoke_case<false, int, foo&>
107 ,invoke_case<false, void, foo&&>
108 ,invoke_case<true, void, std::reference_wrapper<foo>>
109 ,invoke_case<false, int, std::reference_wrapper<foo>>
110 ,invoke_case<false, void, foo const>
111 ,invoke_case<false, void, foo const*>
112 ,invoke_case<false, void, foo const&>
113 ,invoke_case<false, void, foo const&&>
114 ,invoke_case<false, void, std::reference_wrapper<foo const>>
115 ,invoke_case<false, void, foo, int>
116 ,invoke_case<false, void, foo*, int>
117 ,invoke_case<false, void, foo&, int>
118 ,invoke_case<false, void, foo&&, int>
119 ,invoke_case<false, void, std::reference_wrapper<foo>, int>
120 >();
121
122 run_tests<void(foo::*)() RREF
123 ,invoke_case<true, void, foo>
124 ,invoke_case<false, int, foo>
125 ,invoke_case<false, void, foo*>
126 ,invoke_case<false, void, foo&>
127 ,invoke_case<true, void, foo&&>
128 ,invoke_case<false, int, foo&&>
129 ,invoke_case<false, void, std::reference_wrapper<foo>>
130 ,invoke_case<false, void, foo const>
131 ,invoke_case<false, void, foo const*>
132 ,invoke_case<false, void, foo const&>
133 ,invoke_case<false, void, foo const&&>
134 ,invoke_case<false, void, std::reference_wrapper<foo const>>
135 ,invoke_case<false, void, foo, int>
136 ,invoke_case<false, void, foo*, int>
137 ,invoke_case<false, void, foo&, int>
138 ,invoke_case<false, void, foo&&, int>
139 ,invoke_case<false, void, std::reference_wrapper<foo>, int>
140 >();
141
142 run_tests<void(foo::*)() const
143 ,invoke_case<true, void, foo>
144 ,invoke_case<true, void, foo*>
145 ,invoke_case<true, void, foo&>
146 ,invoke_case<true, void, foo&&>
147 ,invoke_case<true, void, std::reference_wrapper<foo>>
148 ,invoke_case<true, void, foo const>
149 ,invoke_case<true, void, foo const*>
150 ,invoke_case<true, void, foo const&>
151 ,invoke_case<true, void, foo const&&>
152 ,invoke_case<true, void, std::reference_wrapper<foo const>>
153 ,invoke_case<false, int, foo>
154 ,invoke_case<false, int, foo*>
155 ,invoke_case<false, int, foo&>
156 ,invoke_case<false, int, foo&&>
157 ,invoke_case<false, int, std::reference_wrapper<foo>>
158 ,invoke_case<false, int, foo const>
159 ,invoke_case<false, int, foo const*>
160 ,invoke_case<false, int, foo const&>
161 ,invoke_case<false, int, foo const&&>
162 ,invoke_case<false, int, std::reference_wrapper<foo const>>
163 ,invoke_case<false, void, foo, int>
164 ,invoke_case<false, void, foo*, int>
165 ,invoke_case<false, void, foo&, int>
166 ,invoke_case<false, void, foo&&, int>
167 ,invoke_case<false, void, std::reference_wrapper<foo>, int>
168 >();
169
170 // MSVC doesn't handle cv + ref qualifiers in expression sfinae correctly
171 #ifndef BOOST_CLBL_TRTS_MSVC
172
173 run_tests<void(foo::*)() const LREF
174 ,invoke_case<false, void, foo>
175 ,invoke_case<true, void, foo*>
176 ,invoke_case<true, void, foo&>
177 ,invoke_case<false, int, foo*>
178 ,invoke_case<false, int, foo&>
179 ,invoke_case<false, void, foo&&>
180 ,invoke_case<true, void, std::reference_wrapper<foo>>
181 ,invoke_case<false, int, std::reference_wrapper<foo>>
182 ,invoke_case<false, void, foo const>
183 ,invoke_case<true, void, foo const*>
184 ,invoke_case<true, void, foo const&>
185 ,invoke_case<false, int, foo const*>
186 ,invoke_case<false, int, foo const&>
187 ,invoke_case<false, void, foo const&&>
188 ,invoke_case<true, void, std::reference_wrapper<foo const>>
189 ,invoke_case<false, int, std::reference_wrapper<foo const>>
190 ,invoke_case<false, void, foo, int>
191 ,invoke_case<false, void, foo*, int>
192 ,invoke_case<false, void, foo&, int>
193 ,invoke_case<false, void, foo&&, int>
194 ,invoke_case<false, void, std::reference_wrapper<foo>, int>
195 >();
196
197 run_tests<void(foo::*)() const RREF
198 ,invoke_case<true, void, foo>
199 ,invoke_case<false, int, foo>
200 ,invoke_case<false, void, foo*>
201 ,invoke_case<false, void, foo&>
202 ,invoke_case<true, void, foo&&>
203 ,invoke_case<false, int, foo&&>
204 ,invoke_case<false, void, std::reference_wrapper<foo>>
205 ,invoke_case<true, void, foo const>
206 ,invoke_case<false, int, foo const>
207 ,invoke_case<false, void, foo const*>
208 ,invoke_case<false, void, foo const&>
209 ,invoke_case<true, void, foo const&&>
210 ,invoke_case<false, int, foo const&&>
211 ,invoke_case<false, void, std::reference_wrapper<foo const>>
212 ,invoke_case<false, void, foo, int>
213 ,invoke_case<false, void, foo*, int>
214 ,invoke_case<false, void, foo&, int>
215 ,invoke_case<false, void, foo&&, int>
216 ,invoke_case<false, void, std::reference_wrapper<foo>, int>
217 >();
218
219 #endif // #ifndef BOOST_CLBL_TRTS_MSVC
220
221 run_tests<int
222 ,invoke_case<false, void, foo>
223 ,invoke_case<false, void, foo*>
224 ,invoke_case<false, void, foo&>
225 ,invoke_case<false, void, foo&&>
226 ,invoke_case<false, void, std::reference_wrapper<foo>>
227 ,invoke_case<false, void, foo const>
228 ,invoke_case<false, void, foo const*>
229 ,invoke_case<false, void, foo const&>
230 ,invoke_case<false, void, foo const&&>
231 ,invoke_case<false, void, std::reference_wrapper<foo const>>
232 ,invoke_case<false, void, foo, int>
233 ,invoke_case<false, void, foo*, int>
234 ,invoke_case<false, void, foo&, int>
235 ,invoke_case<false, void, foo&&, int>
236 ,invoke_case<false, void, std::reference_wrapper<foo>, int>
237 >();
238
239 auto f = [](int){};
240
241 run_tests<decltype(f)
242 ,invoke_case<true, void, int>
243 ,invoke_case<true, void, char>
244 ,invoke_case<false, int, int>
245 ,invoke_case<false, int, char>
246 ,invoke_case<false, void, void*>
247 >();
248
249 auto g = [](){};
250
251 run_tests<decltype(g)
252 ,invoke_case<true, void>
253 ,invoke_case<true, void>
254 ,invoke_case<false, void, int>
255 ,invoke_case<false, void, char>
256 ,invoke_case<false, int, int>
257 ,invoke_case<false, int, char>
258 ,invoke_case<false, void, void*>
259 >();
260
261 // libc++ requires constructible types be passed to std::is_invocable
262 #ifndef _LIBCPP_VERSION
263
264 run_tests<void(int)
265 ,invoke_case<true, void, int>
266 ,invoke_case<true, void, char>
267 ,invoke_case<false, int, int>
268 ,invoke_case<false, int, char>
269 ,invoke_case<false, void, void*>
270 >();
271
272 run_tests<void()
273 ,invoke_case<false, void, int>
274 ,invoke_case<false, void, char>
275 ,invoke_case<false, void, void*>
276 >();
277
278 run_tests<void
279 ,invoke_case<false, void, foo>
280 ,invoke_case<false, void, foo*>
281 ,invoke_case<false, void, foo&>
282 ,invoke_case<false, void, foo&&>
283 ,invoke_case<false, void, std::reference_wrapper<foo>>
284 ,invoke_case<false, void, foo const>
285 ,invoke_case<false, void, foo const*>
286 ,invoke_case<false, void, foo const&>
287 ,invoke_case<false, void, foo const&&>
288 ,invoke_case<false, void, std::reference_wrapper<foo const>>
289 ,invoke_case<false, void, foo, int>
290 ,invoke_case<false, void, foo*, int>
291 ,invoke_case<false, void, foo&, int>
292 ,invoke_case<false, void, foo&&, int>
293 ,invoke_case<false, void, std::reference_wrapper<foo>, int>
294 >();
295 #endif
296
297 run_tests<int
298 ,invoke_case<false, void, foo>
299 ,invoke_case<false, void, foo*>
300 ,invoke_case<false, void, foo&>
301 ,invoke_case<false, void, foo&&>
302 ,invoke_case<false, void, std::reference_wrapper<foo>>
303 ,invoke_case<false, void, foo const>
304 ,invoke_case<false, void, foo const*>
305 ,invoke_case<false, void, foo const&>
306 ,invoke_case<false, void, foo const&&>
307 ,invoke_case<false, void, std::reference_wrapper<foo const>>
308 ,invoke_case<false, void, foo, int>
309 ,invoke_case<false, void, foo*, int>
310 ,invoke_case<false, void, foo&, int>
311 ,invoke_case<false, void, foo&&, int>
312 ,invoke_case<false, void, std::reference_wrapper<foo>, int>
313 >();
314
315 run_tests<void*
316 ,invoke_case<false, void, foo>
317 ,invoke_case<false, void, foo*>
318 ,invoke_case<false, void, foo&>
319 ,invoke_case<false, void, foo&&>
320 ,invoke_case<false, void, std::reference_wrapper<foo>>
321 ,invoke_case<false, void, foo const>
322 ,invoke_case<false, void, foo const*>
323 ,invoke_case<false, void, foo const&>
324 ,invoke_case<false, void, foo const&&>
325 ,invoke_case<false, void, std::reference_wrapper<foo const>>
326 ,invoke_case<false, void, foo, int>
327 ,invoke_case<false, void, foo*, int>
328 ,invoke_case<false, void, foo&, int>
329 ,invoke_case<false, void, foo&&, int>
330 ,invoke_case<false, void, std::reference_wrapper<foo>, int>
331 >();
332 }
333
334 #endif //#ifdef BOOST_CLBL_TRTS_GCC_OLDER_THAN_4_9_2
335