Gamp v0.0.8
Gamp: Graphics, Audio, Multimedia and Processing
Loading...
Searching...
No Matches
test_functional.hpp
Go to the documentation of this file.
1/*
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright (c) 2020 Gothel Software e.K.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24#include <cassert>
25#include <cstring>
26#include <memory>
27#include <string>
28#include <typeindex>
29
30#ifndef FUNCTIONAL_PROVIDED
31 #define FUNCTIONAL_IMPL 1
32 #include <jau/functional.hpp>
33 static std::string impl_name = "jau/functional.hpp";
34#endif
35
36#include <jau/type_cue.hpp>
37
38#include <jau/test/catch2_ext.hpp>
39
40using namespace jau;
41
42// Test examples.
43
44static int Func0a_free(int i) noexcept {
45 int res = i+100;
46 return res;
47}
48
49static void Func1a_free(int&r, int i) noexcept {
50 r = i+100;
51}
52
53static void Func2a_free() noexcept {
54 // nop
55}
56
58 private:
59 int m_i1;
60 int m_i2;
61
62 public:
64 : m_i1(1), m_i2(2)
65 {}
66
67 int i1() const noexcept { return m_i1; }
68 int i2() const noexcept { return m_i2; }
69};
70typedef std::shared_ptr<TrivialObj> TrivialObjSRef;
71
73 private:
74 int m_i1;
75 int m_i2;
76 void *m_mem;
77
78 public:
80 : m_i1(1), m_i2(2), m_mem(::malloc(1024))
81 {}
82
84 if(m_mem) {
85 ::free(m_mem);
86 m_mem = nullptr;
87 }
88 }
90 : m_i1(o.m_i1), m_i2(o.m_i2), m_mem(::malloc(1024)) {
91 ::memcpy(m_mem, o.m_mem, 1024);
92 }
94 : m_i1(o.m_i1), m_i2(o.m_i2), m_mem(o.m_mem) {
95 o.m_mem = nullptr;
96 }
97 int i1() const noexcept { return m_i1; }
98 int i2() const noexcept { return m_i2; }
99 void* handle() const noexcept { return m_mem; }
100};
101typedef std::shared_ptr<NonTrivialObj> NonTrivialObjSRef;
102
104 public:
105
106 /**
107 * Unit test covering most variants of jau::function<R(A...)
108 */
110 INFO("Test 00_usage: START: Implementation = functional "+std::to_string( FUNCTIONAL_IMPL )+".hpp");
111 fprintf(stderr, "Implementation: functional %d, is_rtti_available %d, limited_lambda_id %d\n",
113 {
114 // Test null
115 {
116 function<int(int)> fa0;
117 function<int(int)> fa1 = nullptr;
118 REQUIRE( jau::func::target_type::null == fa0.type() );
119 REQUIRE( jau::func::target_type::null == fa1.type() );
120 }
121 {
122 typedef jau::function<bool(std::vector<uint8_t>& /* data */, bool /* is_final */)> SomeFunc;
123 SomeFunc fa0;
124 SomeFunc fa1 = nullptr;
125 REQUIRE( jau::func::target_type::null == fa0.type() );
126 REQUIRE( jau::func::target_type::null == fa1.type() );
127 }
128 }
129 {
130 // Test capturing lambdas
131 volatile int i = 100;
132
133 function<int(int)> fa0 = [&](int a) -> int {
134 return i + a;
135 };
136 fprintf(stderr, "lambda.0: %s, signature %s\n", fa0.toString().c_str(), fa0.signature().internal_name());
137 REQUIRE( jau::func::target_type::lambda == fa0.type() );
138
139 function<int(int)> fa1 = lambda_01();
140 fprintf(stderr, "lambda.1: %s, signature %s\n", fa1.toString().c_str(), fa1.signature().internal_name());
141 REQUIRE( jau::func::target_type::lambda == fa1.type() );
142
143 auto fa2_stub = [&](int a) -> int {
144 return i + a;
145 };
146 function<int(int)> fa2_a = fa2_stub;
147 fprintf(stderr, "lambda.2_a: %s, signature %s\n", fa2_a.toString().c_str(), fa2_a.signature().internal_name());
148 REQUIRE( jau::func::target_type::lambda == fa2_a.type() );
149
150 function<int(int)> fa2_b = fa2_stub;
151 fprintf(stderr, "lambda.2_b: %s, signature %s\n", fa2_b.toString().c_str(), fa2_b.signature().internal_name());
152 REQUIRE( jau::func::target_type::lambda == fa2_b.type() );
153
154 test_function0_result_____("lambda.0_1_", 1, 101, fa0, fa1);
155 test_function0________type("lambda.0_1_", false, fa0, fa1);
156 test_function0_result_____("lambda.0_2a", 1, 101, fa0, fa2_a);
157 test_function0_result_____("lambda.0_2b", 1, 101, fa0, fa2_b);
158 if constexpr ( jau::type_info::limited_lambda_id ) {
159 if( fa0 == fa2_a ) {
160 fprintf(stderr, "INFO: limited_lambda_id: %s:%d\n", __FILE__, __LINE__);
161 } else {
162 fprintf(stderr, "INFO: limited_lambda_id FIXED: %s:%d\n", __FILE__, __LINE__);
163 test_function0________type("lambda.0_2a", false, fa0, fa2_a);
164 }
165 if( fa0 == fa2_b ) {
166 fprintf(stderr, "INFO: limited_lambda_id: %s:%d\n", __FILE__, __LINE__);
167 } else {
168 fprintf(stderr, "INFO: limited_lambda_id FIXED: %s:%d\n", __FILE__, __LINE__);
169 test_function0________type("lambda.0_2b", false, fa0, fa2_b);
170 }
171 } else {
172 fprintf(stderr, "INFO: !limited_lambda_id: %s:%d\n", __FILE__, __LINE__);
173 test_function0________type("lambda.0_2a", false, fa0, fa2_a);
174 test_function0________type("lambda.0_2b", false, fa0, fa2_b);
175 }
176 test_function0_result_____("lambda.2a2b", 1, 101, fa2_a, fa2_b);
177 test_function0________type("lambda.2a2b", true, fa2_a, fa2_b);
178 }
179
180#if ( FUNCTIONAL_IMPL == 1 )
181 {
182 // Test non-capturing lambdas
183 function<int(int)> f_1 = [](int a) -> int {
184 return a + 100;
185 } ;
186 fprintf(stderr, "lambda.3_1 (plain) %s, signature %s\n", f_1.toString().c_str(), f_1.signature().internal_name());
187 REQUIRE( jau::func::target_type::lambda == f_1.type() );
188 test_function0_result_type("lambda.3131", true, 1, 101, f_1, f_1);
189
190 function<int(int)> f_2 = function<int(int)>::bind_lambda( [](int x) -> int {
191 return x + 100;
192 } );
193 fprintf(stderr, "lambda.3_2 (plain) %s, signature %s\n", f_2.toString().c_str(), f_2.signature().internal_name());
194 REQUIRE( jau::func::target_type::lambda == f_2.type() );
195 test_function0_result_type("lambda.3232", true, 1, 101, f_2, f_2);
196 }
197 {
198 // Test non-capturing y-lambdas, using auto
199 function<int(int)> f_1 = function<int(int)>::bind_ylambda( [](auto& self, int x) -> int {
200 if( 0 == x ) {
201 return 1;
202 } else {
203 return x * self(x-1);
204 }
205 } );
206 fprintf(stderr, "ylambda.1_1 (plain) %s, signature %s\n", f_1.toString().c_str(), f_1.signature().internal_name());
207 REQUIRE( jau::func::target_type::ylambda == f_1.type() );
208 test_function0_result_type("ylambda.1111", true, 4, 24, f_1, f_1);
209 }
210 {
211 // Test non-capturing y-lambdas, using explicit function<int(int)>::delegate_type
212 function<int(int)> f_1 = function<int(int)>::bind_ylambda( [](function<int(int)>::delegate_type& self, int x) -> int {
213 if( 0 == x ) {
214 return 1;
215 } else {
216 return x * self(x-1);
217 }
218 } );
219 fprintf(stderr, "ylambda.1_2 (plain) %s, signature %s\n", f_1.toString().c_str(), f_1.signature().internal_name());
220 REQUIRE( jau::func::target_type::ylambda == f_1.type() );
221 test_function0_result_type("ylambda.1111", true, 4, 24, f_1, f_1);
222 }
223#endif
224 {
225 // Test non-capturing lambdas -> forced free functions
226 typedef int(*cfunc)(int); // to force non-capturing lambda into a free function template type deduction
227 volatile int i = 100;
228
229 auto f = ( [](int a) -> int {
230 // return i + a;
231 return a + 100;
232 } );
233 function<int(int)> fl_ = bind_free<int, int>( (cfunc) f);
234 fprintf(stderr, "plain lambda.0 %s\n", fl_.toString().c_str());
235 REQUIRE( jau::func::target_type::free == fl_.type() );
236
237 test_function0_result_type("FuncPtr1a_free_10", true, 1, 101, fl_, fl_);
238 (void)i;
239
240 }
241 {
242 // free, result void and no params
243 typedef void(*cfunc)();
244 function<void()> fl_0 = (cfunc) ( []() -> void {
245 // nop
246 } );
247 fprintf(stderr, "freeA.0 %s\n", fl_0.toString().c_str());
248 REQUIRE( jau::func::target_type::free == fl_0.type() );
249
250 function<void()> f2a_0 = Func2a_free;
251 fprintf(stderr, "freeA.1 %s\n", f2a_0.toString().c_str());
252 REQUIRE( jau::func::target_type::free == f2a_0.type() );
253
254 function<void()> f2a_1 = bind_free(Func2a_free);
255 fprintf(stderr, "freeA.2 %s\n", f2a_1.toString().c_str());
256 REQUIRE( jau::func::target_type::free == f2a_1.type() );
257
258 function<void()> f20a_1 = bind_free(&TestFunction01::Func20a_static);
259 fprintf(stderr, "freeA.3 %s\n", f20a_1.toString().c_str());
260 REQUIRE( jau::func::target_type::free == f20a_1.type() );
261
262 function<void()> f20a_2 = bind_free(&TestFunction01::Func20a_static);
263 fprintf(stderr, "freeA.4 %s\n", f20a_2.toString().c_str());
264 REQUIRE( jau::func::target_type::free == f20a_2.type() );
265
266 test_function2________type("FuncPtr1a_free_10", true, fl_0, fl_0);
267 test_function2________type("FuncPtr1a_free_10", true, f2a_0, f2a_1);
268 test_function2________type("FuncPtr1a_free_10", true, f2a_1, f2a_1);
269 test_function2________type("FuncPtr3a_free_11", true, f20a_1, f20a_1);
270 test_function2________type("FuncPtr3a_free_12", true, f20a_1, f20a_2);
271 test_function2________type("FuncPtr1a_free_10", false, f2a_1, f20a_1);
272
273 }
274 {
275 // free, result non-void
276 typedef int(*cfunc)(int); // to force non-capturing lambda into a free function template type deduction
277 function<int(int)> fl_0 = (cfunc) ( [](int i) -> int {
278 int res = i+100;
279 return res;
280 } );
281 fprintf(stderr, "freeB.0 %s\n", fl_0.toString().c_str());
282 REQUIRE( jau::func::target_type::free == fl_0.type() );
283
284 function<int(int)> f1a_0 = Func0a_free;
285 fprintf(stderr, "freeB.1 %s\n", f1a_0.toString().c_str());
286 REQUIRE( jau::func::target_type::free == f1a_0.type() );
287
288 function<int(int)> f1a_1 = bind_free(Func0a_free);
289 function<int(int)> f3a_1 = bind_free(&TestFunction01::Func03a_static);
290 function<int(int)> f3a_2 = bind_free(&TestFunction01::Func03a_static);
291 test_function0_result_type("FuncPtr1a_free_10", true, 1, 101, fl_0, fl_0);
292 test_function0_result_type("FuncPtr1a_free_10", true, 1, 101, f1a_0, f1a_1);
293 test_function0_result_type("FuncPtr1a_free_10", true, 1, 101, f1a_1, f1a_1);
294 test_function0_result_type("FuncPtr3a_free_11", true, 1, 101, f3a_1, f3a_1);
295 test_function0_result_type("FuncPtr3a_free_12", true, 1, 101, f3a_1, f3a_2);
296 test_function0_result_type("FuncPtr1a_free_10", false, 1, 101, f1a_1, f3a_1);
297 }
298 {
299 // free, result void
300 typedef void(*cfunc)(int&, int); // to force non-capturing lambda into a free function template type deduction
301 function<void(int&, int)> fl_0 = (cfunc) ( [](int& res, int i) -> void {
302 res = i+100;
303 } );
304 function<void(int&, int)> f1a_0 = Func1a_free;
305 function<void(int&, int)> f1a_1 = bind_free(Func1a_free);
306 function<void(int&, int)> f3a_0 = &TestFunction01::Func13a_static;
307 function<void(int&, int)> f3a_1 = bind_free(&TestFunction01::Func13a_static);
308 function<void(int&, int)> f3a_2 = bind_free(&TestFunction01::Func13a_static);
309 test_function1_result_type("FuncPtr1a_free_10", true, 1, 101, fl_0, fl_0);
310 test_function1_result_type("FuncPtr1a_free_10", true, 1, 101, f1a_1, f1a_0);
311 test_function1_result_type("FuncPtr3a_free_11", true, 1, 101, f3a_1, f3a_0);
312 test_function1_result_type("FuncPtr3a_free_11", true, 1, 101, f3a_1, f3a_1);
313 test_function1_result_type("FuncPtr3a_free_12", true, 1, 101, f3a_1, f3a_2);
314 test_function1_result_type("FuncPtr1a_free_10", false, 1, 101, f1a_1, f3a_1);
315 }
316 {
317 // member, result non-void
318 function<int(int)> f2a_0(this, &TestFunction01::func02a_member);
319 fprintf(stderr, "memberA.0 %s\n", f2a_0.toString().c_str());
320 REQUIRE( jau::func::target_type::member == f2a_0.type() );
321
322 function<int(int)> f2a_1 = bind_member(this, &TestFunction01::func02a_member);
323 fprintf(stderr, "memberA.1 %s\n", f2a_1.toString().c_str());
324 REQUIRE( jau::func::target_type::member == f2a_1.type() );
325
326 function<int(int)> f2a_2 = bind_member(this, &TestFunction01::func02a_member);
327 function<int(int)> f2b_1 = bind_member(this, &TestFunction01::func02b_member);
328 test_function0_result_type("FuncPtr2a_member_12", true, 1, 101, f2a_1, f2a_0);
329 test_function0_result_type("FuncPtr2a_member_12", true, 1, 101, f2a_1, f2a_2);
330 test_function0_result_type("FuncPtr2a_member_12", false, 1, 101, f2a_1, f2b_1);
331 }
332 {
333 // member, result void
334 function<void(int&, int)> f2a_0(this, &TestFunction01::func12a_member);
335 function<void(int&, int)> f2a_1 = bind_member(this, &TestFunction01::func12a_member);
336 function<void(int&, int)> f2a_2 = bind_member(this, &TestFunction01::func12a_member);
337 function<void(int&, int)> f2b_1 = bind_member(this, &TestFunction01::func12b_member);
338 test_function1_result_type("FuncPtr2a_member_12", true, 1, 101, f2a_1, f2a_0);
339 test_function1_result_type("FuncPtr2a_member_12", true, 1, 101, f2a_1, f2a_2);
340 test_function1_result_type("FuncPtr2a_member_12", false, 1, 101, f2a_1, f2b_1);
341 }
342 {
343 // Lambda alike w/ explicit capture by value, result non-void
344 int offset100 = 100;
345
346 typedef int(*cfunc)(int&, int); // to force non-capturing lambda into a free function template type deduction
347
348 int(*func5a_capture)(int&, int) = [](int& capture, int i)->int {
349 int res = i+10000+capture;
350 return res;
351 };
352
353 int(*func5b_capture)(int&, int) = [](int& capture, int i)->int {
354 int res = i+100000+capture;
355 return res;
356 };
357
358 function<int(int)> f5_o100_0(offset100,
359 (cfunc) ( [](int& capture, int i)->int {
360 int res = i+10000+capture;
361 return res;
362 } ) );
363 fprintf(stderr, "capvalA.0 %s\n", f5_o100_0.toString().c_str());
364 REQUIRE( jau::func::target_type::capval == f5_o100_0.type() );
365
366 function<int(int)> f5_o100_1 = bind_capval(offset100,
367 (cfunc) ( [](int& capture, int i)->int {
368 int res = i+10000+capture;
369 return res;
370 } ) );
371 function<int(int)> f5_o100_2 = bind_capval(offset100,
372 (cfunc) ( [](int& capture, int i)->int {
373 int res = i+10000+capture;
374 return res;
375 } ) );
376 test_function0________type("FuncPtr5a_o100_capture_00", true, f5_o100_0, f5_o100_0);
377 test_function0________type("FuncPtr5a_o100_capture_00", true, f5_o100_1, f5_o100_1);
378 test_function0________type("FuncPtr5a_o100_capture_00", false, f5_o100_1, f5_o100_2);
379
380 function<int(int)> f5a_o100_0(offset100, func5a_capture);
381 fprintf(stderr, "capvalA.1 %s\n", f5a_o100_0.toString().c_str());
382 REQUIRE( jau::func::target_type::capval == f5a_o100_0.type() );
383
384 function<int(int)> f5a_o100_1 = bind_capval(offset100, func5a_capture);
385 function<int(int)> f5a_o100_2 = bind_capval(offset100, func5a_capture);
386 function<int(int)> f5b_o100_1 = bind_capval(offset100, func5b_capture);
387 test_function0________type("FuncPtr5a_o100_capture_12", true, f5a_o100_1, f5a_o100_0);
388 test_function0________type("FuncPtr5a_o100_capture_12", true, f5a_o100_1, f5a_o100_2);
389 test_function0________type("FuncPtr5a_o100_capture_12", false, f5a_o100_1, f5b_o100_1);
390 test_function0_result_type("FuncPtr5a_o100_capture_11", true, 1, 10101, f5a_o100_1, f5a_o100_1);
391 test_function0_result_type("FuncPtr5a_o100_capture_12", true, 1, 10101, f5a_o100_1, f5a_o100_2);
392 test_function0_result_type("FuncPtr5a_o100_capture_12", false, 1, 10101, f5a_o100_1, f5b_o100_1);
393 }
394 {
395 // Lambda alike w/ explicit capture by reference, result non-void
396 IntOffset offset100(100);
397
398 typedef int(*cfunc)(IntOffset*, int); // to force non-capturing lambda into a free function template type deduction
399
400 int(*func7a_capture)(IntOffset*, int) = [](IntOffset* capture, int i)->int {
401 int res = i+10000+capture->value;
402 return res;
403 };
404 int(*func7b_capture)(IntOffset*, int) = [](IntOffset* capture, int i)->int {
405 int res = i+100000+capture->value;
406 return res;
407 };
408
409 function<int(int)> f7_o100_1 = bind_capref<int, IntOffset, int>(&offset100,
410 (cfunc) ( [](IntOffset* capture, int i)->int {
411 int res = i+10000+capture->value;
412 return res;;
413 } ) );
414 fprintf(stderr, "caprefA.0 %s\n", f7_o100_1.toString().c_str());
415 REQUIRE( jau::func::target_type::capref == f7_o100_1.type() );
416
417 function<int(int)> f7_o100_2 = bind_capref<int, IntOffset, int>(&offset100,
418 (cfunc) ( [](IntOffset* capture, int i)->int {
419 int res = i+10000+capture->value;
420 return res;;
421 } ) );
422 test_function0________type("FuncPtr7a_o100_capture_00", true, f7_o100_1, f7_o100_1);
423 test_function0________type("FuncPtr7a_o100_capture_00", false, f7_o100_1, f7_o100_2);
424
425 function<int(int)> f7a_o100_1 = bind_capref(&offset100, func7a_capture);
426 fprintf(stderr, "caprefA.1 %s\n", f7a_o100_1.toString().c_str());
427 REQUIRE( jau::func::target_type::capref == f7a_o100_1.type() );
428 function<int(int)> f7a_o100_2 = bind_capref(&offset100, func7a_capture);
429 function<int(int)> f7b_o100_1 = bind_capref(&offset100, func7b_capture);
430 test_function0________type("FuncPtr7a_o100_capture_12", true, f7a_o100_1, f7a_o100_2);
431 test_function0________type("FuncPtr7a_o100_capture_12", false, f7a_o100_1, f7b_o100_1);
432 test_function0_result_type("FuncPtr7a_o100_capture_11", true, 1, 10101, f7a_o100_1, f7a_o100_1);
433 test_function0_result_type("FuncPtr7a_o100_capture_12", true, 1, 10101, f7a_o100_1, f7a_o100_2);
434 test_function0_result_type("FuncPtr7a_o100_capture_12", false, 1, 10101, f7a_o100_1, f7b_o100_1);
435 }
436 {
437 // std::function lambda
438 std::function<int(int i)> func4a_stdlambda = [](int i)->int {
439 int res = i+100;
440 return res;;
441 };
442 std::function<int(int i)> func4b_stdlambda = [](int i)->int {
443 int res = i+1000;
444 return res;;
445 };
446 function<int(int)> f4a_1 = bind_std(100, func4a_stdlambda);
447 fprintf(stderr, "stdfunc.0 %s\n", f4a_1.toString().c_str());
448 REQUIRE( jau::func::target_type::std == f4a_1.type() );
449
450 function<int(int)> f4a_2 = bind_std(100, func4a_stdlambda);
451 test_function0_result_type("FuncPtr4a_stdlambda_11", true, 1, 101, f4a_1, f4a_1);
452 test_function0_result_type("FuncPtr4a_stdlambda_12", true, 1, 101, f4a_1, f4a_2);
453 }
454
455 INFO("Test 00_usage: END");
456 }
457
459 INFO("Test 01_member: bind_member<int, TestFunction01, int>: START");
460 {
461 // function(TestFunction01 &base, Func1Type func)
462 MyClassFunction0 f2a_1 = bind_member<int, TestFunction01, int>(this, &TestFunction01::func02a_member);
463 MyClassFunction0 f2a_2 = bind_member(this, &TestFunction01::func02a_member);
464 test_function0_result_type("FuncPtr2a_member_11", true, 1, 101, f2a_1, f2a_1);
465 test_function0_result_type("FuncPtr2a_member_12", true, 1, 101, f2a_1, f2a_2);
466
467 MyClassFunction0 f2b_1 = bind_member(this, &TestFunction01::func02b_member);
468 MyClassFunction0 f2b_2 = bind_member(this, &TestFunction01::func02b_member);
469 test_function0_result_type("FuncPtr2b_member_11", true, 1, 1001, f2b_1, f2b_1);
470 test_function0_result_type("FuncPtr2b_member_12", true, 1, 1001, f2b_1, f2b_2);
471
472 test_function0_result_type("FuncPtr2ab_member_11", false, 1, 0, f2a_1, f2b_1);
473 test_function0_result_type("FuncPtr2ab_member_22", false, 1, 0, f2a_2, f2b_2);
474 }
475
476 {
477 std::string msg = "member01_c1";
478
479 struct c1_t {
480 int offset;
481
482 int f(int i) noexcept {
483 int res = i+offset;
484 return res;
485 }
486 };
487 c1_t c_1a { 100 };
488 c1_t c_1b { 100 };
489 function<int(int)> f_1a(&c_1a, &c1_t::f);
490 function<int(int)> f_1b(&c_1b, &c1_t::f);
491 fprintf(stderr, "%s 1a %s\n", msg.c_str(), f_1a.toString().c_str());
492 REQUIRE( jau::func::target_type::member == f_1a.type() );
493 fprintf(stderr, "%s 1b %s\n", msg.c_str(), f_1b.toString().c_str());
494 REQUIRE( jau::func::target_type::member == f_1b.type() );
495
496 c1_t c_2a { 1000 };
497 c1_t c_2b { 1000 };
498 function<int(int)> f_2a(&c_2a, &c1_t::f);
499 function<int(int)> f_2b(&c_2b, &c1_t::f);
500 fprintf(stderr, "%s 2a %s\n", msg.c_str(), f_2a.toString().c_str());
501 REQUIRE( jau::func::target_type::member == f_2a.type() );
502 fprintf(stderr, "%s 2b %s\n", msg.c_str(), f_2b.toString().c_str());
503 REQUIRE( jau::func::target_type::member == f_2b.type() );
504
505 test_function0_result_____(msg+" 1aa", 1, 101, f_1a, f_1a);
506 test_function0_result_____(msg+" 1ab", 1, 101, f_1a, f_1b);
507 test_function0________type(msg+" 1aa", true, f_1a, f_1a);
508 test_function0________type(msg+" 1ab", false, f_1a, f_1b);
509
510 test_function0_result_____(msg+" 2aa", 1, 1001, f_2a, f_2a);
511 test_function0_result_____(msg+" 2ab", 1, 1001, f_2a, f_2b);
512 test_function0________type(msg+" 2aa", true, f_2a, f_2a);
513 test_function0________type(msg+" 2ab", false, f_2a, f_2b);
514 }
515
516 {
517 struct c1_t {
518 int offset;
519
520 c1_t() : offset(10) {}
521 c1_t(int v) : offset(v) {}
522
523 int f(int i) noexcept {
524 int res = i+offset; /** (B) EXPECTED if c2_t is referenced. **/
525 return res;
526 }
527 };
528
529 struct c2_t : public c1_t {
530 c2_t() : c1_t() {}
531 c2_t(int v) : c1_t(v) {}
532
533 int f(int i) noexcept {
534 int res = i+1000; /** (A) EXPECTED if c2_t is referenced. **/
535 return res;
536 }
537 };
538
539 /**
540 * (A) Create a function delegate using c2_t spec and c2_t reference for actual c2_t instance,
541 * expect to use c2_t function definition!
542 */
543 {
544 std::string msg = "member02_func_c2";
545
546 c2_t c_1a ( 100 );
547 c2_t c_1b ( 100 );
548
549 function<int(int)> f_1a(&c_1a, &c2_t::f);
550 function<int(int)> f_1b(&c_1b, &c2_t::f);
551 fprintf(stderr, "%s 1a %s\n", msg.c_str(), f_1a.toString().c_str());
552 REQUIRE( jau::func::target_type::member == f_1a.type() );
553 fprintf(stderr, "%s 1b %s\n", msg.c_str(), f_1b.toString().c_str());
554 REQUIRE( jau::func::target_type::member == f_1b.type() );
555
556 test_function0_result_____(msg+" 1aa", 1, 1001, f_1a, f_1a);
557 test_function0_result_____(msg+" 1ab", 1, 1001, f_1a, f_1b);
558 test_function0________type(msg+" 1aa", true, f_1a, f_1a);
559 test_function0________type(msg+" 1ab", false, f_1a, f_1b);
560 }
561
562 /**
563 * (B) Create a function delegate using c1_t spec and c1_t reference for actual c2_t instance,
564 * expect to use c1_t function definition!
565 */
566 {
567 std::string msg = "member03_func_c1_ref";
568
569 c2_t c_1a_ ( 100 );
570 c2_t c_1b_ ( 100 );
571 c1_t& c_1a = c_1a_;
572 c1_t& c_1b = c_1b_;
573
574 function<int(int)> f_1a(&c_1a, &c1_t::f);
575 function<int(int)> f_1b(&c_1b, &c1_t::f);
576 fprintf(stderr, "%s 1a %s\n", msg.c_str(), f_1a.toString().c_str());
577 REQUIRE( jau::func::target_type::member == f_1a.type() );
578 fprintf(stderr, "%s 1b %s\n", msg.c_str(), f_1b.toString().c_str());
579 REQUIRE( jau::func::target_type::member == f_1b.type() );
580
581 test_function0_result_____(msg+" 1aa", 1, 101, f_1a, f_1a);
582 test_function0_result_____(msg+" 1ab", 1, 101, f_1a, f_1b);
583 test_function0________type(msg+" 1aa", true, f_1a, f_1a);
584 test_function0________type(msg+" 1ab", false, f_1a, f_1b);
585 }
586 }
587
588 {
589 struct c1_t {
590 int offset; /** (A) EXPECTED if c1_t is referenced. **/
591
592 c1_t() : offset(10) {}
593
594 int f(int i) noexcept {
595 int res = i+offset;
596 return res;
597 }
598 };
599
600 struct c2_t : public c1_t {
601 int offset; /** (B) EXPECTED if c2_t is referenced. **/
602
603 c2_t() : c1_t(), offset(20) {}
604 c2_t(int v) : c1_t(), offset(v) {}
605 };
606
607 struct c3_t : public c2_t {
608 c3_t() : c2_t() {}
609 c3_t(int v) : c2_t(v) {}
610 };
611
612 /**
613 * (0) Compile error, since given this base-pointer type c4_t (C1)
614 * is not derived from type c1_t (C0) holding the member-function.
615 */
616 {
617#if 0
618 struct c4_t {
619 };
620 c4_t c_1a;
621 function<int(int)> f_1a(&c_1a, &c1_t::f);
622#endif
623 }
624
625 /**
626 * (A) Create a function delegate using c2_t spec and c2_t reference for actual c2_t instance,
627 * expect to use c1_t offset member!
628 */
629 {
630 std::string msg = "member04_field_c2";
631
632 c2_t c_1a( 1000 );
633 c3_t c_1b( 1000 );
634
635 REQUIRE( 1000 == c_1a.offset);
636 fprintf(stderr, "%s offset: c2_t %d\n", msg.c_str(), c_1a.offset);
637
638 function<int(int)> f_1a(&c_1a, &c1_t::f);
639 function<int(int)> f_1b(&c_1b, &c1_t::f);
640 fprintf(stderr, "%s 1a %s\n", msg.c_str(), f_1a.toString().c_str());
641 REQUIRE( jau::func::target_type::member == f_1a.type() );
642 fprintf(stderr, "%s 1b %s\n", msg.c_str(), f_1b.toString().c_str());
643 REQUIRE( jau::func::target_type::member == f_1b.type() );
644
645 test_function0_result_____(msg+" 1aa", 1, 11, f_1a, f_1a);
646 test_function0_result_____(msg+" 1ab", 1, 11, f_1a, f_1b);
647 test_function0________type(msg+" 1aa", true, f_1a, f_1a);
648 test_function0________type(msg+" 1ab", false, f_1a, f_1b);
649 }
650 /**
651 * (B) Create a function delegate using c1_t spec and c1_t reference for actual c2_t instance,
652 * expect to use c1_t offset member!
653 */
654 {
655 std::string msg = "member05_field_c1_ref";
656
657 c2_t c_1a_( 1000 );
658 c3_t c_1b_( 1000 );
659 c1_t& c_1a = c_1a_;
660 c1_t& c_1b = c_1b_;
661
662 REQUIRE( 1000 == c_1a_.offset);
663 REQUIRE( 10 == c_1a.offset);
664 fprintf(stderr, "%s offset: c2_t %d, c1_t ref %d\n", msg.c_str(), c_1a_.offset, c_1a.offset);
665
666 function<int(int)> f_1a(&c_1a, &c1_t::f);
667 function<int(int)> f_1b(&c_1b, &c1_t::f);
668 fprintf(stderr, "%s 1a %s\n", msg.c_str(), f_1a.toString().c_str());
669 REQUIRE( jau::func::target_type::member == f_1a.type() );
670 fprintf(stderr, "%s 1b %s\n", msg.c_str(), f_1b.toString().c_str());
671 REQUIRE( jau::func::target_type::member == f_1b.type() );
672
673 test_function0_result_____(msg+" 1aa", 1, 11, f_1a, f_1a);
674 test_function0_result_____(msg+" 1ab", 1, 11, f_1a, f_1b);
675 test_function0________type(msg+" 1aa", true, f_1a, f_1a);
676 test_function0________type(msg+" 1ab", false, f_1a, f_1b);
677 }
678 }
679
680 /**
681 * Create a function delegate using c1_t spec and c1_t reference for actual c2_t instance,
682 * expect to use c2_t virtual override!
683 */
684 {
685 std::string msg = "member06_vfunc_c1_ref";
686
687 struct c1_t {
688 int offset;
689
690 c1_t() : offset(10) {}
691 c1_t(int v) : offset(v) {}
692
693 virtual ~c1_t() noexcept = default;
694
695 virtual int f(int i) noexcept {
696 int res = i+offset;
697 return res;
698 }
699 };
700
701 struct c2_t : public c1_t {
702 c2_t() : c1_t() {}
703 c2_t(int v) : c1_t(v) {}
704
705 int f(int i) noexcept override {
706 int res = i+1000;
707 return res;
708 }
709 };
710 c2_t c_1a_( 100 );
711 c2_t c_1b_( 100 );
712 c1_t& c_1a = c_1a_;
713 c1_t& c_1b = c_1b_;
714
715 function<int(int)> f_1a(&c_1a, &c1_t::f);
716 function<int(int)> f_1b(&c_1b, &c1_t::f);
717 fprintf(stderr, "%s 1a %s\n", msg.c_str(), f_1a.toString().c_str());
718 REQUIRE( jau::func::target_type::member == f_1a.type() );
719 fprintf(stderr, "%s 1b %s\n", msg.c_str(), f_1b.toString().c_str());
720 REQUIRE( jau::func::target_type::member == f_1b.type() );
721
722 test_function0_result_____(msg+" 1aa", 1, 1001, f_1a, f_1a);
723 test_function0_result_____(msg+" 1ab", 1, 1001, f_1a, f_1b);
724 test_function0________type(msg+" 1aa", true, f_1a, f_1a);
725 test_function0________type(msg+" 1ab", false, f_1a, f_1b);
726 }
727 INFO("Test 01_member: bind_member<int, TestFunction01, int>: END");
728 }
729
731 INFO("Test 11_member: bind_member<int, TestFunction01, int>: START");
732 // function(TestFunction01 &base, Func1Type func)
733 MyClassFunction1 f2a_1 = bind_member<TestFunction01, int&, int>(this, &TestFunction01::func12a_member);
734 MyClassFunction1 f2a_2 = bind_member(this, &TestFunction01::func12a_member);
735 test_function1_result_type("FuncPtr2a_member_11", true, 1, 101, f2a_1, f2a_1);
736 test_function1_result_type("FuncPtr2a_member_12", true, 1, 101, f2a_1, f2a_2);
737
738 MyClassFunction1 f2b_1 = bind_member(this, &TestFunction01::func12b_member);
739 MyClassFunction1 f2b_2 = bind_member(this, &TestFunction01::func12b_member);
740 test_function1_result_type("FuncPtr2b_member_11", true, 1, 1001, f2b_1, f2b_1);
741 test_function1_result_type("FuncPtr2b_member_12", true, 1, 1001, f2b_1, f2b_2);
742
743 test_function1_result_type("FuncPtr2ab_member_11", false, 1, 0, f2a_1, f2b_1);
744 test_function1_result_type("FuncPtr2ab_member_22", false, 1, 0, f2a_2, f2b_2);
745 INFO("Test 11_member: bind_member<int, TestFunction01, int>: END");
746 }
747
749 INFO("Test 02_free: bind_free<int, int>: START");
750 // function(Func1Type func)
751 MyClassFunction0 f1a_1 = bind_free<int, int>(Func0a_free);
752 MyClassFunction0 f3a_1 = bind_free<int, int>(&TestFunction01::Func03a_static);
753 MyClassFunction0 f3a_2 = bind_free(&TestFunction01::Func03a_static);
754 test_function0_result_type("FuncPtr1a_free_10", true, 1, 101, f1a_1, f1a_1);
755 test_function0_result_type("FuncPtr3a_free_11", true, 1, 101, f3a_1, f3a_1);
756 test_function0_result_type("FuncPtr3a_free_12", true, 1, 101, f3a_1, f3a_2);
757
758 MyClassFunction0 f3b_1 = bind_free(&TestFunction01::Func03b_static);
759 MyClassFunction0 f3b_2 = bind_free(&Func03b_static);
760 test_function0_result_type("FuncPtr3b_free_11", true, 1, 1001, f3b_1, f3b_1);
761 test_function0_result_type("FuncPtr3b_free_12", true, 1, 1001, f3b_1, f3b_2);
762
763 test_function0_result_type("FuncPtr1a3a_free_10", false, 1, 0, f1a_1, f3a_1);
764 test_function0_result_type("FuncPtr1a3b_free_10", false, 1, 0, f1a_1, f3b_1);
765 test_function0_result_type("FuncPtr3a3b_free_11", false, 1, 0, f3a_1, f3b_1);
766 test_function0_result_type("FuncPtr3a3b_free_22", false, 1, 0, f3a_2, f3b_2);
767 INFO("Test 02_free: bind_free<int, int>: END");
768 }
769
771 INFO("Test 12_free: bind_free<int, int>: START");
772 // function(Func1Type func)
773 MyClassFunction1 f1a_1 = bind_free<int&, int>(Func1a_free);
774 MyClassFunction1 f3a_1 = bind_free<int&, int>(&TestFunction01::Func13a_static);
775 MyClassFunction1 f3a_2 = bind_free(&TestFunction01::Func13a_static);
776 test_function1_result_type("FuncPtr1a_free_10", true, 1, 101, f1a_1, f1a_1);
777 test_function1_result_type("FuncPtr3a_free_11", true, 1, 101, f3a_1, f3a_1);
778 test_function1_result_type("FuncPtr3a_free_12", true, 1, 101, f3a_1, f3a_2);
779
780 MyClassFunction1 f3b_1 = bind_free(&TestFunction01::Func13b_static);
781 MyClassFunction1 f3b_2 = bind_free(&Func13b_static);
782 test_function1_result_type("FuncPtr3b_free_11", true, 1, 1001, f3b_1, f3b_1);
783 test_function1_result_type("FuncPtr3b_free_12", true, 1, 1001, f3b_1, f3b_2);
784
785 test_function1_result_type("FuncPtr1a3a_free_10", false, 1, 0, f1a_1, f3a_1);
786 test_function1_result_type("FuncPtr1a3b_free_10", false, 1, 0, f1a_1, f3b_1);
787 test_function1_result_type("FuncPtr3a3b_free_11", false, 1, 0, f3a_1, f3b_1);
788 test_function1_result_type("FuncPtr3a3b_free_22", false, 1, 0, f3a_2, f3b_2);
789 INFO("Test 12_free: bind_free<int, int>: END");
790 }
791
793 INFO("Test 03_stdlambda: bind_std<int, int>: START");
794 // function(Func1Type func) <int, int>
795 std::function<int(int i)> func4a_stdlambda = [](int i)->int {
796 int res = i+100;
797 return res;;
798 };
799 jau::type_cue<std::function<int(int i)>>::print("std::function<int(int i)> type", TypeTraitGroup::ALL);
800
801 std::function<int(int i)> func4b_stdlambda = [](int i)->int {
802 int res = i+1000;
803 return res;;
804 };
805 MyClassFunction0 f4a_1 = bind_std<int, int>(100, func4a_stdlambda);
806 MyClassFunction0 f4a_2 = bind_std(100, func4a_stdlambda);
807 test_function0_result_type("FuncPtr4a_stdlambda_11", true, 1, 101, f4a_1, f4a_1);
808 test_function0_result_type("FuncPtr4a_stdlambda_12", true, 1, 101, f4a_1, f4a_2);
809
810 MyClassFunction0 f4b_1 = bind_std(200, func4b_stdlambda);
811 MyClassFunction0 f4b_2 = bind_std(200, func4b_stdlambda);
812 test_function0_result_type("FuncPtr4b_stdlambda_11", true, 1, 1001, f4b_1, f4b_1);
813 test_function0_result_type("FuncPtr4b_stdlambda_12", true, 1, 1001, f4b_1, f4b_2);
814
815 test_function0_result_type("FuncPtr4ab_stdlambda_11", false, 1, 0, f4a_1, f4b_1);
816 test_function0_result_type("FuncPtr4ab_stdlambda_22", false, 1, 0, f4a_2, f4b_2);
817
818 INFO("Test 03_stdlambda: bind_std<int, int>: END");
819 }
820
822 INFO("Test 13_stdlambda: bind_std<int, int>: START");
823 // function(Func1Type func) <int, int>
824 std::function<void(int& r, int i)> func4a_stdlambda = [](int& r, int i)->void {
825 r = i+100;
826 };
827 jau::type_cue<std::function<void(int& r, int i)>>::print("std::function<int(int i)> type", TypeTraitGroup::ALL);
828
829 std::function<void(int& r, int i)> func4b_stdlambda = [](int& r, int i)->void {
830 r = i+1000;
831 };
832 MyClassFunction1 f4a_1 = bind_std<int&, int>(100, func4a_stdlambda);
833 MyClassFunction1 f4a_2 = bind_std(100, func4a_stdlambda);
834 test_function1_result_type("FuncPtr4a_stdlambda_11", true, 1, 101, f4a_1, f4a_1);
835 test_function1_result_type("FuncPtr4a_stdlambda_12", true, 1, 101, f4a_1, f4a_2);
836
837 MyClassFunction1 f4b_1 = bind_std(200, func4b_stdlambda);
838 MyClassFunction1 f4b_2 = bind_std(200, func4b_stdlambda);
839 test_function1_result_type("FuncPtr4b_stdlambda_11", true, 1, 1001, f4b_1, f4b_1);
840 test_function1_result_type("FuncPtr4b_stdlambda_12", true, 1, 1001, f4b_1, f4b_2);
841
842 test_function1_result_type("FuncPtr4ab_stdlambda_11", false, 1, 0, f4a_1, f4b_1);
843 test_function1_result_type("FuncPtr4ab_stdlambda_22", false, 1, 0, f4a_2, f4b_2);
844
845 INFO("Test 13_stdlambda: bind_std<int, int>: END");
846 }
847
849 INFO("Test 04_capval: bindCapture<int, int, int>: START");
850 // bindCapture(I& data, R(*func)(I&, A...))
851 // function(Func1Type func) <int, int>
852 int offset100 = 100;
853 int offset1000 = 1000;
854
855 typedef int(*cfunc)(int&, int); // to force non-capturing lambda into a free function template type deduction
856
857 int(*func5a_capture)(int&, int) = [](int& capture, int i)->int {
858 int res = i+10000+capture;
859 return res;
860 };
861 int(*func5b_capture)(int&, int) = [](int& capture, int i)->int {
862 int res = i+100000+capture;
863 return res;
864 };
865
866 MyClassFunction0 f5a_o100_0 = bind_capval<int, int, int>(offset100,
867 (cfunc) ( [](int& capture, int i)->int {
868 int res = i+10000+capture;
869 return res;;
870 } ) );
871 test_function0________type("FuncPtr5a_o100_capture_00", true, f5a_o100_0, f5a_o100_0);
872
873 MyClassFunction0 f5a_o100_1 = bind_capval<int, int, int>(offset100, func5a_capture);
874 MyClassFunction0 f5a_o100_2 = bind_capval(offset100, func5a_capture);
875 test_function0________type("FuncPtr5a_o100_capture_12", true, f5a_o100_1, f5a_o100_2);
876 test_function0_result_type("FuncPtr5a_o100_capture_11", true, 1, 10101, f5a_o100_1, f5a_o100_1);
877 test_function0_result_type("FuncPtr5a_o100_capture_12", true, 1, 10101, f5a_o100_1, f5a_o100_2);
878 // test_FunctionPointer01("FuncPtr5a_o100_capture_01", false, f5a_o100_0, f5a_o100_1);
879 MyClassFunction0 f5a_o1000_1 = bind_capval(offset1000, func5a_capture);
880 MyClassFunction0 f5a_o1000_2 = bind_capval(offset1000, func5a_capture);
881 test_function0________type("FuncPtr5a_o1000_capture_12", true, f5a_o1000_1, f5a_o1000_2);
882 test_function0________type("FuncPtr5a_o100_o1000_capture_11", false, f5a_o100_1, f5a_o1000_1);
883
884 MyClassFunction0 f5b_o100_1 = bind_capval(offset100, func5b_capture);
885 MyClassFunction0 f5b_o100_2 = bind_capval(offset100, func5b_capture);
886 test_function0_result_type("FuncPtr5b_o100_capture_11", true, 1, 100101, f5b_o100_1, f5b_o100_1);
887 test_function0_result_type("FuncPtr5b_o100_capture_12", true, 1, 100101, f5b_o100_1, f5b_o100_2);
888
889 test_function0_result_type("FuncPtr5ab_o100_capture_11", false, 1, 0, f5a_o100_1, f5b_o100_1);
890 test_function0_result_type("FuncPtr5ab_o100_capture_22", false, 1, 0, f5a_o100_2, f5b_o100_2);
891 INFO("Test 04_capval: bindCapture<int, int, int>: END");
892 }
893
895 INFO("Test 14_capval: bindCapture<int, int, int>: START");
896 // bindCapture(I& data, R(*func)(I&, A...))
897 // function(Func1Type func) <int, int>
898 int offset100 = 100;
899 int offset1000 = 1000;
900
901 typedef void(*cfunc)(int&, int&, int); // to force non-capturing lambda into a free function template type deduction
902
903 void(*func5a_capture)(int&, int&, int) = [](int& capture, int& res, int i)->void {
904 res = i+10000+capture;
905 };
906 void(*func5b_capture)(int&, int&, int) = [](int& capture, int& res, int i)->void {
907 res = i+100000+capture;
908 };
909
910 MyClassFunction1 f5a_o100_0 = bind_capval<int, int&, int>(offset100,
911 (cfunc) ( [](int& capture, int& res, int i)->void {
912 res = i+10000+capture;
913 } ) );
914 test_function1________type("FuncPtr5a_o100_capture_00", true, f5a_o100_0, f5a_o100_0);
915
916 MyClassFunction1 f5a_o100_1 = bind_capval<int, int&, int>(offset100, func5a_capture);
917 MyClassFunction1 f5a_o100_2 = bind_capval(offset100, func5a_capture);
918 test_function1________type("FuncPtr5a_o100_capture_12", true, f5a_o100_1, f5a_o100_2);
919 test_function1_result_type("FuncPtr5a_o100_capture_11", true, 1, 10101, f5a_o100_1, f5a_o100_1);
920 test_function1_result_type("FuncPtr5a_o100_capture_12", true, 1, 10101, f5a_o100_1, f5a_o100_2);
921 // test_FunctionPointer01("FuncPtr5a_o100_capture_01", false, f5a_o100_0, f5a_o100_1);
922 MyClassFunction1 f5a_o1000_1 = bind_capval(offset1000, func5a_capture);
923 MyClassFunction1 f5a_o1000_2 = bind_capval(offset1000, func5a_capture);
924 test_function1________type("FuncPtr5a_o1000_capture_12", true, f5a_o1000_1, f5a_o1000_2);
925 test_function1________type("FuncPtr5a_o100_o1000_capture_11", false, f5a_o100_1, f5a_o1000_1);
926
927 MyClassFunction1 f5b_o100_1 = bind_capval(offset100, func5b_capture);
928 MyClassFunction1 f5b_o100_2 = bind_capval(offset100, func5b_capture);
929 test_function1_result_type("FuncPtr5b_o100_capture_11", true, 1, 100101, f5b_o100_1, f5b_o100_1);
930 test_function1_result_type("FuncPtr5b_o100_capture_12", true, 1, 100101, f5b_o100_1, f5b_o100_2);
931
932 test_function1_result_type("FuncPtr5ab_o100_capture_11", false, 1, 0, f5a_o100_1, f5b_o100_1);
933 test_function1_result_type("FuncPtr5ab_o100_capture_22", false, 1, 0, f5a_o100_2, f5b_o100_2);
934 INFO("Test 14_capval: bindCapture<int, int, int>: END");
935 }
936
938 INFO("Test 05_capval: bindCapture<int, std::shared_ptr<IntOffset>, int>: START");
939 // bindCapture(I& data, R(*func)(I&, A...))
940 // function(Func1Type func) <int, int>
941 std::shared_ptr<IntOffset> offset100(new IntOffset(100));
942 std::shared_ptr<IntOffset> offset1000(new IntOffset(1000));
943
944 typedef int(*cfunc)(std::shared_ptr<IntOffset>&, int); // to force non-capturing lambda into a free function template type deduction
945
946 int(*func6a_capture)(std::shared_ptr<IntOffset>&, int) = [](std::shared_ptr<IntOffset>& capture, int i)->int {
947 int res = i+10000+capture->value;
948 return res;
949 };
950 int(*func6b_capture)(std::shared_ptr<IntOffset>&, int) = [](std::shared_ptr<IntOffset>& capture, int i)->int {
951 int res = i+100000+capture->value;
952 return res;
953 };
954
955 MyClassFunction0 f6a_o100_0 = bind_capval<int, std::shared_ptr<IntOffset>, int>(offset100,
956 (cfunc) ( [](std::shared_ptr<IntOffset>& sharedOffset, int i)->int {
957 int res = i+10000+sharedOffset->value;
958 return res;;
959 } ) );
960 test_function0________type("FuncPtr6a_o100_capture_00", true, f6a_o100_0, f6a_o100_0);
961
962 MyClassFunction0 f6a_o100_1 = bind_capval<int, std::shared_ptr<IntOffset>, int>(offset100, func6a_capture);
963 MyClassFunction0 f6a_o100_2 = bind_capval(offset100, func6a_capture);
964 test_function0________type("FuncPtr6a_o100_capture_12", true, f6a_o100_1, f6a_o100_2);
965 test_function0_result_type("FuncPtr6a_o100_capture_11", true, 1, 10101, f6a_o100_1, f6a_o100_1);
966 test_function0_result_type("FuncPtr6a_o100_capture_12", true, 1, 10101, f6a_o100_1, f6a_o100_2);
967 // test_FunctionPointer01("FuncPtr6a_o100_capture_01", false, f6a_o100_0, f6a_o100_1);
968 MyClassFunction0 f6a_o1000_1 = bind_capval(offset1000, func6a_capture);
969 MyClassFunction0 f6a_o1000_2 = bind_capval(offset1000, func6a_capture);
970 test_function0________type("FuncPtr6a_o1000_capture_12", true, f6a_o1000_1, f6a_o1000_2);
971 test_function0________type("FuncPtr6a_o100_o1000_capture_11", false, f6a_o100_1, f6a_o1000_1);
972
973 MyClassFunction0 f6b_o100_1 = bind_capval(offset100, func6b_capture);
974 MyClassFunction0 f6b_o100_2 = bind_capval(offset100, func6b_capture);
975 test_function0_result_type("FuncPtr6b_o100_capture_11", true, 1, 100101, f6b_o100_1, f6b_o100_1);
976 test_function0_result_type("FuncPtr6b_o100_capture_12", true, 1, 100101, f6b_o100_1, f6b_o100_2);
977
978 test_function0_result_type("FuncPtr6ab_o100_capture_11", false, 1, 0, f6a_o100_1, f6b_o100_1);
979 test_function0_result_type("FuncPtr6ab_o100_capture_22", false, 1, 0, f6a_o100_2, f6b_o100_2);
980 INFO("Test 05_capval: bindCapture<int, std::shared_ptr<IntOffset>, int>: END");
981 }
982
984 INFO("Test 06_capval: bindCapture<int, IntOffset, int>: START");
985 // bindCapture(I& data, R(*func)(I&, A...))
986 // function(Func1Type func) <int, int>
987 IntOffset offset100(100);
988 IntOffset offset1000(1000);
989
990 typedef int(*cfunc)(IntOffset&, int); // to force non-capturing lambda into a free function template type deduction
991
992 int(*func7a_capture)(IntOffset&, int) = [](IntOffset& capture, int i)->int {
993 int res = i+10000+capture.value;
994 return res;
995 };
996 int(*func7b_capture)(IntOffset&, int) = [](IntOffset& capture, int i)->int {
997 int res = i+100000+capture.value;
998 return res;
999 };
1000
1001 MyClassFunction0 f7a_o100_0 = bind_capval<int, IntOffset, int>(offset100,
1002 (cfunc) ( [](IntOffset& capture, int i)->int {
1003 int res = i+10000+capture.value;
1004 return res;;
1005 } ) );
1006 test_function0________type("FuncPtr7a_o100_capture_00", true, f7a_o100_0, f7a_o100_0);
1007
1008 INFO("f7a_o100_1 copy_ctor");
1009 MyClassFunction0 f7a_o100_1 = bind_capval<int, IntOffset, int>(offset100, func7a_capture);
1010 INFO("f7a_o100_1 copy_ctor done");
1011 INFO("f7a_o100_2 move_ctor");
1012 MyClassFunction0 f7a_o100_2 = bind_capval(IntOffset(100), func7a_capture);
1013 INFO("f7a_o100_2 move_ctor done");
1014 test_function0________type("FuncPtr7a_o100_capture_12", true, f7a_o100_1, f7a_o100_2);
1015 test_function0_result_type("FuncPtr7a_o100_capture_11", true, 1, 10101, f7a_o100_1, f7a_o100_1);
1016 test_function0_result_type("FuncPtr7a_o100_capture_12", true, 1, 10101, f7a_o100_1, f7a_o100_2);
1017 // test_FunctionPointer01("FuncPtr7a_o100_capture_01", false, f7a_o100_0, f7a_o100_1);
1018 MyClassFunction0 f7a_o1000_1 = bind_capval(offset1000, func7a_capture);
1019 MyClassFunction0 f7a_o1000_2 = bind_capval(offset1000, func7a_capture);
1020 test_function0________type("FuncPtr7a_o1000_capture_12", true, f7a_o1000_1, f7a_o1000_2);
1021 test_function0________type("FuncPtr7a_o100_o1000_capture_11", false, f7a_o100_1, f7a_o1000_1);
1022
1023 MyClassFunction0 f7b_o100_1 = bind_capval(offset100, func7b_capture);
1024 MyClassFunction0 f7b_o100_2 = bind_capval(offset100, func7b_capture);
1025 test_function0_result_type("FuncPtr7b_o100_capture_11", true, 1, 100101, f7b_o100_1, f7b_o100_1);
1026 test_function0_result_type("FuncPtr7b_o100_capture_12", true, 1, 100101, f7b_o100_1, f7b_o100_2);
1027
1028 test_function0_result_type("FuncPtr7ab_o100_capture_11", false, 1, 0, f7a_o100_1, f7b_o100_1);
1029 test_function0_result_type("FuncPtr7ab_o100_capture_22", false, 1, 0, f7a_o100_2, f7b_o100_2);
1030 INFO("Test 06_capval: bindCapture<int, IntOffset, int>: END");
1031 }
1032
1034 INFO("Test 07_capref: bindCapture<int, IntOffset, int>: START");
1035 // bindCapture(I& data, R(*func)(I&, A...))
1036 // function(Func1Type func) <int, int>
1037 IntOffset offset100(100);
1038 IntOffset offset1000(1000);
1039
1040 typedef int(*cfunc)(IntOffset*, int); // to force non-capturing lambda into a free function template type deduction
1041
1042 int(*func7a_capture)(IntOffset*, int) = [](IntOffset* capture, int i)->int {
1043 int res = i+10000+capture->value;
1044 return res;
1045 };
1046 int(*func7b_capture)(IntOffset*, int) = [](IntOffset* capture, int i)->int {
1047 int res = i+100000+capture->value;
1048 return res;
1049 };
1050
1051 MyClassFunction0 f7a_o100_0 = bind_capref<int, IntOffset, int>(&offset100,
1052 (cfunc) ( [](IntOffset* capture, int i)->int {
1053 int res = i+10000+capture->value;
1054 return res;;
1055 } ) );
1056 test_function0________type("FuncPtr7a_o100_capture_00", true, f7a_o100_0, f7a_o100_0);
1057
1058 INFO("f7a_o100_1 copy_ctor");
1059 MyClassFunction0 f7a_o100_1 = bind_capref<int, IntOffset, int>(&offset100, func7a_capture);
1060 INFO("f7a_o100_1 copy_ctor done");
1061 INFO("f7a_o100_2 move_ctor");
1062 MyClassFunction0 f7a_o100_2 = bind_capref(&offset100, func7a_capture);
1063 INFO("f7a_o100_2 move_ctor done");
1064 test_function0________type("FuncPtr7a_o100_capture_12", true, f7a_o100_1, f7a_o100_2);
1065 test_function0_result_type("FuncPtr7a_o100_capture_11", true, 1, 10101, f7a_o100_1, f7a_o100_1);
1066 test_function0_result_type("FuncPtr7a_o100_capture_12", true, 1, 10101, f7a_o100_1, f7a_o100_2);
1067 // test_FunctionPointer01("FuncPtr7a_o100_capture_01", false, f7a_o100_0, f7a_o100_1);
1068 MyClassFunction0 f7a_o1000_1 = bind_capref(&offset1000, func7a_capture);
1069 MyClassFunction0 f7a_o1000_2 = bind_capref(&offset1000, func7a_capture);
1070 test_function0________type("FuncPtr7a_o1000_capture_12", true, f7a_o1000_1, f7a_o1000_2);
1071 test_function0________type("FuncPtr7a_o100_o1000_capture_11", false, f7a_o100_1, f7a_o1000_1);
1072
1073 MyClassFunction0 f7b_o100_1 = bind_capref(&offset100, func7b_capture);
1074 MyClassFunction0 f7b_o100_2 = bind_capref(&offset100, func7b_capture);
1075 test_function0_result_type("FuncPtr7b_o100_capture_11", true, 1, 100101, f7b_o100_1, f7b_o100_1);
1076 test_function0_result_type("FuncPtr7b_o100_capture_12", true, 1, 100101, f7b_o100_1, f7b_o100_2);
1077
1078 test_function0_result_type("FuncPtr7ab_o100_capture_11", false, 1, 0, f7a_o100_1, f7b_o100_1);
1079 test_function0_result_type("FuncPtr7ab_o100_capture_22", false, 1, 0, f7a_o100_2, f7b_o100_2);
1080 INFO("Test 07_capref: bindCapture<int, IntOffset, int>: END");
1081 }
1082
1084 {
1085 volatile int i = 100;
1086
1087 auto fa0_stub = ( [&](int a) -> int {
1088 return i + a;
1089 } );
1090 typedef decltype(fa0_stub) fa0_type;
1092
1093 // function<int(int)> fa0 = jau::bind_lambda<int, fa0_type, int>( fa0_stub );
1094 function<int(int)> fa0 = fa0_stub;
1095
1096 fprintf(stderr, "fa0.2: %s\n", fa0.toString().c_str());
1097 REQUIRE( jau::func::target_type::lambda == fa0.type() );
1098
1099 test_function0_result_type("lambda.2", true, 1, 101, fa0, fa0);
1100 }
1101 {
1102 volatile int i = 100;
1103
1104 auto fa0_stub = ( [i](int a) -> int {
1105 return i + a;
1106 } );
1107 typedef decltype(fa0_stub) fa0_type;
1109
1110 function<int(int)> fa0( fa0_stub );
1111
1112 fprintf(stderr, "fa0.3: %s\n", fa0.toString().c_str());
1113 REQUIRE( jau::func::target_type::lambda == fa0.type() );
1114
1115 test_function0_result_type("lambda.3", true, 1, 101, fa0, fa0);
1116 }
1117 {
1118 volatile int i = 100;
1119
1120 function<int(int)> fa0 = [i](int a) -> int {
1121 return i + a;
1122 };
1123
1124 fprintf(stderr, "fa0.4: %s\n", fa0.toString().c_str());
1125 REQUIRE( jau::func::target_type::lambda == fa0.type() );
1126
1127 test_function0_result_type("lambda.4", true, 1, 101, fa0, fa0);
1128 }
1129 {
1130 volatile int i = 100;
1131
1132 function<int(int)> fa0 = [&](int a) -> int {
1133 return i + a;
1134 };
1135
1136 fprintf(stderr, "fa0.4: %s\n", fa0.toString().c_str());
1137 REQUIRE( jau::func::target_type::lambda == fa0.type() );
1138
1139 test_function0_result_type("lambda.4", true, 1, 101, fa0, fa0);
1140 }
1141 {
1142#if 0
1143 function<void(int)> f0 = jau::bind_lambda( [&i](int a) -> void {
1144 int r = i + a;
1145 (void)r;
1146 } );
1147 (void)f0;
1148
1149 function<int(int)> f = jau::bind_lambda( [&i](int a) -> int {
1150 return i + a;
1151 } );
1152 test_function0_result_type("FuncPtr1a_free_10", true, 1, 101, f, f);
1153#endif
1154 }
1155 }
1156
1158 volatile int i = 100;
1159 // volatile int j = 100;
1160
1161 MyCFunc0 f_0 = (MyCFunc0) ( [](int a) -> int {
1162 return 100 + a;
1163 } );
1164 const char* f0_name = jau::ctti_name<decltype(f_0)>();
1165 REQUIRE( jau::type_info::is_valid( f0_name ) );
1166 jau::type_info f_0_type(f0_name);
1167 std::string f0_str(f0_name);
1168 fprintf(stderr, "f_0: %s\n", f0_name);
1169
1170 auto f_a = [&](int a) -> int {
1171 return i + a;
1172 };
1173 const char* fa_name = jau::ctti_name<decltype(f_a)>();
1174 REQUIRE( jau::type_info::is_valid( fa_name ) );
1175 std::string fa_str(fa_name);
1176 fprintf(stderr, "f_a: %s\n", fa_name);
1177
1178 {
1179 // Limitation: Non unique function pointer type names with same prototype
1180 jau::type_info f_b_type;
1181 fprintf(stderr, "empty type: %s\n", f_b_type.internal_name());
1182
1183 MyCFunc0 f_b = cfunction_00(f_b_type);
1184 // We must instantiate the ctti_name from its source location,
1185 // otherwise it is missing for RTTI and CTTI - rendering it the same!
1186 //
1187 // const char* fb_name = jau::ctti_name<decltype(f_b)>();
1188 // REQUIRE( jau::type_info::is_valid( fb_name ) );
1189 const char* fb_name = f_b_type.internal_name();
1190 std::string fb_str(fb_name);
1191 fprintf(stderr, "f_b: %s\n", fb_name);
1192
1193#if defined(__cxx_rtti_available__)
1194 std::type_index f_0_t(typeid(f_0));
1195 fprintf(stderr, "f_0_t: %s\n", f_0_t.name());
1196 std::type_index f_b_t(typeid(f_b));
1197 fprintf(stderr, "f_b_t: %s\n", f_b_t.name());
1198
1199 if( f_0_t == f_b_t ) {
1200 fprintf(stderr, "INFO: RTTI limitation on functions exists: f_b_t: %s\n", f_b_t.name());
1201 } else {
1202 fprintf(stderr, "INFO: RTTI limitation on functions FIXED: f_b_t: %s\n", f_b_t.name());
1203 }
1204#else
1205 (void)f_b;
1206#endif
1207 if( f0_str == fb_str ) {
1208 fprintf(stderr, "INFO: CTTI limitation on functions exists: f_b: %s\n", fb_str.c_str());
1209 } else {
1210 fprintf(stderr, "INFO: CTTI limitation on functions FIXED: f_b: %s\n", fb_str.c_str());
1211 }
1212 if( f_0_type == f_b_type ) {
1213 fprintf(stderr, "INFO: CTTI limitation on functions exists: f_b_type: %s\n", f_b_type.internal_name());
1214 } else {
1215 fprintf(stderr, "INFO: CTTI limitation on functions FIXED: f_b_type: %s\n", f_b_type.internal_name());
1216 }
1217 }
1218
1219 {
1220 jau::function<int(int)> f_c = lambda_01();
1221 const char* fc_name = jau::ctti_name<decltype(f_c)>();
1222 REQUIRE( jau::type_info::is_valid( fc_name ) );
1223 // std::string fc_str(fc_name);
1224 fprintf(stderr, "fc_name: %s\n", fc_name);
1225 fprintf(stderr, "fc: %s\n", f_c.toString().c_str());
1226 }
1227 {
1228 // NOTE-E: f_e != f_a: Different function prototype (hit), equivalent but different code and same capture than fa2_1!
1229 auto f_e = [&](int a, bool dummy) -> int {
1230 (void)dummy;
1231 return i + a;
1232 };
1233 const char* fe_name = jau::ctti_name<decltype(f_e)>();
1234 REQUIRE( jau::type_info::is_valid( fe_name ) );
1235 std::string fe_str(fe_name);
1236 fprintf(stderr, "fe_name: %s\n", fe_name);
1237
1238 REQUIRE(fa_str != fe_str );
1239 }
1240 }
1241
1243 {
1244 volatile int i = 100;
1245 volatile int j = 100;
1246
1247 auto fa0_stub = ( [&](int a) -> int {
1248 return i + a;
1249 } );
1250
1251 function<int(int)> fa0_a( fa0_stub );
1252 fprintf(stderr, "fa0_a: %s\n", fa0_a.toString().c_str());
1253 REQUIRE( jau::func::target_type::lambda == fa0_a.type() );
1254 {
1255 auto fa0c_stub = ( [&](int a) -> int {
1256 return i + a;
1257 } );
1258 function<int(int)> fa0_c( fa0c_stub );
1259 fprintf(stderr, "fa0_c: %s\n", fa0_c.toString().c_str());
1260 fprintf(stderr, "fa0_stub is_same fa0c_stub: %d\n",
1261 std::is_same_v<decltype(fa0_stub), decltype(fa0c_stub)> );
1262 fprintf(stderr, "fa0_a == fa0_c: %d\n",
1263 fa0_a == fa0_c );
1264 }
1265
1266 // Note-0: Based on same fa0_stub, hence same code and capture!
1267 function<int(int)> fa0_b( fa0_stub );
1268 fprintf(stderr, "fa1: %s\n", fa0_b.toString().c_str());
1269 REQUIRE( jau::func::target_type::lambda == fa0_a.type() );
1270
1271 function<int(int)> fa2_1 = [&](int a) -> int {
1272 return i + a;
1273 };
1274 fprintf(stderr, "fa2_1: %s\n", fa2_1.toString().c_str());
1275 REQUIRE( jau::func::target_type::lambda == fa2_1.type() );
1276
1277 // NOTE-1: fa2_2 != fa2_1: Different code location from function lambda_01(), equivalent code but not same, same capture!
1278 function<int(int)> fa2_2 = lambda_01();
1279 fprintf(stderr, "fa2_2: %s\n", fa2_2.toString().c_str());
1280 REQUIRE( jau::func::target_type::lambda == fa2_2.type() );
1281
1282 // NOTE-2: fa2_3 != fa2_1: Equivalent code but not same, same capture!
1283 // FIXME: No RTTI on GCC produces same __PRETTY_FUNCTION__ based id (just parent function + generic lambda),
1284 // where clang uses filename + line, which works.
1285 function<int(int)> fa2_3 = [&](int a) -> int {
1286 return i + a;
1287 };
1288 fprintf(stderr, "fa2_3: %s\n", fa2_3.toString().c_str());
1289 REQUIRE( jau::func::target_type::lambda == fa2_3.type() );
1290
1291 // NOTE-3: fa2_4 != fa2_1: Different capture type than fa2_1 (but equivalent code)
1292 function<int(int)> fa2_4 = [i](int a) -> int {
1293 return i + a;
1294 };
1295 fprintf(stderr, "fa2_4: %s\n", fa2_4.toString().c_str());
1296 REQUIRE( jau::func::target_type::lambda == fa2_4.type() );
1297
1298 // NOTE-B: f_b != fa2_1: Equivalent but different code and different capture than fa2_1!
1299 // !RTTI GCC: OK (different capture)
1300 function<int(int)> f_b = [&](int a) -> int {
1301 return j + a;
1302 };
1303 fprintf(stderr, "f_b: %s\n", f_b.toString().c_str());
1304 REQUIRE( jau::func::target_type::lambda == f_b.type() );
1305
1306 // NOTE-C: f_c != fa2_1: Different code type and different capture than fa2_1!
1307 // !RTTI GCC: OK (different capture)
1308 function<int(int)> f_c = [&](int a) -> int {
1309 return 2 * ( j + a );
1310 };
1311 fprintf(stderr, "f_c: %s\n", f_c.toString().c_str());
1312 REQUIRE( jau::func::target_type::lambda == f_c.type() );
1313
1314 // NOTE-D: f_d != fa2_1: Different code type than fa2_1, but same capture!
1315 // FIXME: See Note-2 !!!
1316 function<int(int)> f_d = [&](int a) -> int {
1317 return 2 * ( i + a );
1318 };
1319 fprintf(stderr, "f_d: %s\n", f_d.toString().c_str());
1320 REQUIRE( jau::func::target_type::lambda == f_d.type() );
1321
1322 // NOTE-E: f_e != fa2_1: Different function prototype (hit), equivalent but different code and same capture than fa2_1!
1323 function<int(int, bool)> f_e = [&](int a, bool dummy) -> int {
1324 (void)dummy;
1325 return i + a;
1326 };
1327 fprintf(stderr, "f_e: %s\n", f_e.toString().c_str());
1328 REQUIRE( jau::func::target_type::lambda == f_d.type() );
1329
1330 test_function0_result_type("lambda.5b", true, 1, 101, fa2_1, fa2_1); // Same function instance
1331 test_function0_result_type("lambda.5a", true, 1, 101, fa0_a, fa0_b); // Note-0: Same code and capture
1332
1333 test_function0_result_____("lambda.5c", 1, 101, fa2_1, fa2_2); // NOTE-1: Equal result
1334 test_function0________type("lambda.5c", false, fa2_1, fa2_2); // NOTE-1: Diff code
1335 test_function0_result_____("lambda.5e", 1, 101, fa2_1, fa2_4); // NOTE-3: Equal result
1336 test_function0________type("lambda.5e", false, fa2_1, fa2_4); // NOTE-3: Diff capture / code
1337
1338 test_function0________type("lambda.5B", false, fa2_1, f_b); // NOTE-B
1339 test_function0________type("lambda.5C", false, fa2_1, f_c); // NOTE-C
1340
1341 test_function0_result_____("lambda.5d", 1, 101, fa2_1, fa2_3); // NOTE-2: Equal result
1342 if constexpr ( jau::type_info::limited_lambda_id ) {
1343 if( fa2_1 == fa2_3 ) {
1344 fprintf(stderr, "INFO: limited_lambda_id: %s:%d\n", __FILE__, __LINE__);
1345 } else {
1346 fprintf(stderr, "INFO: limited_lambda_id FIXED: %s:%d\n", __FILE__, __LINE__);
1347 test_function0________type("lambda.5d", false, fa2_1, fa2_3); // NOTE-2: Diff code
1348 }
1349 if( fa2_1 == f_d ) {
1350 fprintf(stderr, "INFO: limited_lambda_id: %s:%d\n", __FILE__, __LINE__);
1351 } else {
1352 fprintf(stderr, "INFO: limited_lambda_id FIXED: %s:%d\n", __FILE__, __LINE__);
1353 test_function0________type("lambda.5D", false, fa2_1, f_d); // NOTE-D
1354 }
1355 } else {
1356 fprintf(stderr, "INFO: !limited_lambda_id: %s:%d\n", __FILE__, __LINE__);
1357 test_function0________type("lambda.5d", false, fa2_1, fa2_3); // NOTE-2: Diff code
1358 test_function0________type("lambda.5D", false, fa2_1, f_d); // NOTE-D
1359 }
1360 CHECK(fa2_1 != f_e); // NOTE-D: Diff function prototype
1361 }
1362 {
1363 // lambda capture by reference-1, plain
1364 int i = 100;
1365 int j = 100;
1366 function<int(int)> f_1 = [&i](int a) -> int {
1367 return i + a;
1368 };
1369 fprintf(stderr, "l6 f_1 ref: %s\n", f_1.toString().c_str());
1370 REQUIRE( jau::func::target_type::lambda == f_1.type() );
1371
1372 // NOTE-C: f_1 != f_1: Different code type and different capture than f_1!
1373 // !RTTI GCC: OK (different capture)
1374 function<int(int)> f_2 = [&j](int a) -> int {
1375 return j + a;
1376 };
1377 fprintf(stderr, "l6 f_2 ref: %s\n", f_2.toString().c_str());
1378 REQUIRE( jau::func::target_type::lambda == f_2.type() );
1379
1380 test_function0_result_____("lambda.6", 1, 101, f_1, f_2);
1381 test_function0________type("lambda.6", false, f_1, f_2);
1382 test_function0________type("lambda.6", true, f_1, f_1);
1383 }
1384 {
1385 // lambda capture by reference-2, state-test: mutate used captured reference field
1386 int i = 100;
1387 int j = 100;
1388 function<int(int)> f_1 = [&i](int a) -> int {
1389 int res = i + a;
1390 i+=1;
1391 return res;
1392 };
1393 fprintf(stderr, "l7 f_1 ref: %s\n", f_1.toString().c_str());
1394 REQUIRE( jau::func::target_type::lambda == f_1.type() );
1395
1396 // NOTE-C: f_1 != f_1: Different code type and different capture than f_1!
1397 // !RTTI GCC: OK (different capture)
1398 function<int(int)> f_2 = [&j](int a) -> int {
1399 int res = j + a;
1400 j+=1;
1401 return res;
1402 };
1403 fprintf(stderr, "l7 f_2 ref: %s\n", f_2.toString().c_str());
1404 REQUIRE( jau::func::target_type::lambda == f_2.type() );
1405
1406 test_function0_result_copy("lambda.7.1a", 1, 101, f_1, f_2); // increment of referenced i,j, f_x passed by copy!
1407 test_function0_result_copy("lambda.7.1b", 1, 102, f_1, f_2); // increment of referenced i,j, f_x passed by copy!
1408 test_function0_result_copy("lambda.7.1c", 1, 103, f_1, f_2); // increment of referenced i,j, f_x passed by copy!
1409
1410 test_function0_result_____("lambda.7.2a", 1, 104, f_1, f_2); // increment of referenced i,j, f_x passed by ref
1411 test_function0_result_____("lambda.7.2b", 1, 105, f_1, f_2); // increment of referenced i,j, f_x passed by ref
1412 test_function0_result_____("lambda.7.2c", 1, 106, f_1, f_2); // increment of referenced i,j, f_x passed by ref
1413
1414 test_function0________type("lambda.7.5", false, f_1, f_2);
1415 test_function0________type("lambda.7.5", true, f_1, f_1);
1416 }
1417 {
1418 // lambda capture by copy, plain
1419 int i = 100;
1420 int j = 100;
1421 function<int(int)> f_1 = [i](int a) -> int {
1422 return i + a;
1423 };
1424 fprintf(stderr, "l8 f_1 cpy: %s\n", f_1.toString().c_str());
1425 REQUIRE( jau::func::target_type::lambda == f_1.type() );
1426
1427 // NOTE-C: f_1 != f_1: Different code type and different capture than f_1!
1428 // !RTTI GCC: OK (different capture)
1429 function<int(int)> f_2 = [j](int a) -> int {
1430 return j + a;
1431 };
1432 fprintf(stderr, "l8 f_2 cpy: %s\n", f_2.toString().c_str());
1433 REQUIRE( jau::func::target_type::lambda == f_2.type() );
1434
1435 test_function0_result_____("lambda.8.1", 1, 101, f_1, f_2);
1436 if constexpr ( !jau::type_info::limited_lambda_id ) {
1437 test_function0________type("lambda.8.2", false, f_1, f_2);
1438 } else {
1439 if( f_1 == f_2 ) {
1440 fprintf(stderr, "INFO: limited_lambda_id: %s:%d\n", __FILE__, __LINE__);
1441 } else {
1442 fprintf(stderr, "INFO: limited_lambda_id FIXED: %s:%d\n", __FILE__, __LINE__);
1443 test_function0________type("lambda.8.2", false, f_1, f_2); // NOTE-2: Diff code
1444 }
1445 }
1446 test_function0________type("lambda.8.3", true, f_1, f_1);
1447 }
1448 {
1449 // lambda capture by copy-2, state-test: mutate a static variable
1450 int i = 100;
1451 int j = 100;
1452 function<int(int)> f_1 = [i](int a) -> int {
1453 static int store = i;
1454 int res = store + a;
1455 store+=1;
1456 return res;
1457 };
1458 fprintf(stderr, "l9 f_1 cpy: %s\n", f_1.toString().c_str());
1459 REQUIRE( jau::func::target_type::lambda == f_1.type() );
1460
1461 // NOTE-C: f_1 != f_1: Different code type and different capture than f_1!
1462 // !RTTI GCC: OK (different capture)
1463 function<int(int)> f_2 = [j](int a) -> int {
1464 static int store = j;
1465 int res = store + a;
1466 store+=1;
1467 return res;
1468 };
1469 fprintf(stderr, "l9 f_2 cpy: %s\n", f_2.toString().c_str());
1470 REQUIRE( jau::func::target_type::lambda == f_2.type() );
1471
1472 test_function0_result_copy("lambda.9.1a", 1, 101, f_1, f_2); // increment of static, f_x passed by copy!
1473 test_function0_result_copy("lambda.9.1b", 1, 102, f_1, f_2); // increment of static, f_x passed by copy!
1474 test_function0_result_copy("lambda.9.1c", 1, 103, f_1, f_2); // increment of static, f_x passed by copy!
1475
1476 test_function0_result_____("lambda.9.2a", 1, 104, f_1, f_2); // increment of static, f_x passed by ref
1477 test_function0_result_____("lambda.9.2b", 1, 105, f_1, f_2); // increment of static, f_x passed by ref
1478 test_function0_result_____("lambda.9.2c", 1, 106, f_1, f_2); // increment of static, f_x passed by ref
1479
1480 if constexpr ( !jau::type_info::limited_lambda_id ) {
1481 test_function0________type("lambda.9.5", false, f_1, f_2);
1482 } else {
1483 if( f_1 == f_2 ) {
1484 fprintf(stderr, "INFO: limited_lambda_id: %s:%d\n", __FILE__, __LINE__);
1485 } else {
1486 fprintf(stderr, "INFO: limited_lambda_id FIXED: %s:%d\n", __FILE__, __LINE__);
1487 test_function0________type("lambda.9.5", false, f_1, f_2); // NOTE-2: Diff code
1488 }
1489 }
1490 test_function0________type("lambda.9.5", true, f_1, f_1);
1491 }
1492 {
1493 // lambda capture by copy-3, state-test: mutate used captured copied field, lambda marked as mutable!
1494 //
1495 // Note: This fails w/ old implementation functional2.hpp, i.e. FUNCTIONAL_BROKEN_COPY_WITH_MUTATING_CAPTURE
1496 //
1497 int i = 100;
1498 int j = 100;
1499 function<int(int)> f_1 = [i](int a) mutable -> int {
1500 int res = i + a;
1501 i+=1;
1502 return res;
1503 };
1504 fprintf(stderr, "l10 f_1 cpy: %s\n", f_1.toString().c_str());
1505 REQUIRE( jau::func::target_type::lambda == f_1.type() );
1506
1507 // NOTE-C: f_1 != f_1: Different code type and different capture than f_1!
1508 // !RTTI GCC: OK (different capture)
1509 function<int(int)> f_2 = [j](int a) mutable -> int {
1510 int res = j + a;
1511 j+=1;
1512 return res;
1513 };
1514 fprintf(stderr, "l10 f_2 cpy: %s\n", f_2.toString().c_str());
1515 REQUIRE( jau::func::target_type::lambda == f_2.type() );
1516
1517#if FUNCTIONAL_IMPL == 1
1518 test_function0_result_copy("lambda.10.1a", 1, 101, f_1, f_2); // increment of copied i,j, f_x passed by copy!
1519 test_function0_result_copy("lambda.10.1b", 1, 101, f_1, f_2); // increment of copied i,j, f_x passed by copy!
1520 test_function0_result_copy("lambda.10.1c", 1, 101, f_1, f_2); // increment of copied i,j, f_x passed by copy!
1521#else
1522 fprintf(stderr, "l10 f_2 cpy: FUNCTIONAL_BROKEN_COPY_WITH_MUTABLE_LAMBDA\n");
1523#endif
1524
1525 test_function0_result_____("lambda.10.2a", 1, 101, f_1, f_2); // increment of copied i,j, f_x passed by ref
1526 test_function0_result_____("lambda.10.2b", 1, 102, f_1, f_2); // increment of copied i,j, f_x passed by ref
1527 test_function0_result_____("lambda.10.2c", 1, 103, f_1, f_2); // increment of copied i,j, f_x passed by ref
1528
1529 if constexpr ( !jau::type_info::limited_lambda_id ) {
1530 test_function0________type("lambda.10.5", false, f_1, f_2);
1531 } else {
1532 if( f_1 == f_2 ) {
1533 fprintf(stderr, "INFO: limited_lambda_id: %s:%d\n", __FILE__, __LINE__);
1534 } else {
1535 fprintf(stderr, "INFO: limited_lambda_id FIXED: %s:%d\n", __FILE__, __LINE__);
1536 test_function0________type("lambda.10.5", false, f_1, f_2); // NOTE-2: Diff code
1537 }
1538 }
1539 test_function0________type("lambda.10.5", true, f_1, f_1);
1540 }
1541#if ( FUNCTIONAL_IMPL == 1 )
1542 {
1543 function<int(int)> f_1 = function<int(int)>::bind_ylambda( [](auto& self, int x) -> int {
1544 if( 0 == x ) {
1545 return 1;
1546 } else {
1547 return x * self(x-1);
1548 }
1549 } );
1550 fprintf(stderr, "ylambda 1 f_1: %s\n", f_1.toString().c_str());
1551 REQUIRE( jau::func::target_type::ylambda == f_1.type() );
1552 REQUIRE( 24 == f_1(4) ); // `self` is bound to function<R(A...)>::delegate_type `f_1.target`, `x` is 4
1553
1554 // f_1 != f_2 since both reference a different `self`
1555 function<int(int)> f_2 = function<int(int)>::bind_ylambda( [](auto& self, int x) -> int {
1556 if( 0 == x ) {
1557 return 1;
1558 } else {
1559 return x * self(x-1);
1560 }
1561 } );
1562 test_function0________type("ylambda.1.1", true, f_1, f_1);
1563 test_function0________type("ylambda.1.2", false, f_1, f_2);
1564 }
1565#endif
1566 }
1567
1568 template<typename R, typename L, typename... A>
1570 private:
1571 L f;
1572 public:
1573 // template<typename L>
1575 : f( func )
1576 { }
1577
1578 static constexpr y_combinator_lambda make(L func) {
1579 return y_combinator_lambda<R, L, A...>(func);
1580 }
1581
1582 constexpr R operator()(A... args) const {
1583 return f(*this, args...);
1584 }
1585 constexpr R operator()(A... args) {
1586 return f(*this, args...);
1587 }
1588 };
1589
1591 {
1592 // Using the manual template type y_combinator_lambda, 1st-try
1593 auto stub = [](auto& self, int x) -> int {
1594 if( 0 == x ) {
1595 return 1;
1596 } else {
1597 return x * self(x-1);
1598 }
1599 };
1600 jau::type_cue<decltype(stub)>::print("y_combinator.0.stub", TypeTraitGroup::ALL);
1601 y_combinator_lambda<int, decltype(stub), int> f_1 = stub;
1602 REQUIRE( 24 == f_1(4) );
1603 }
1604#if ( FUNCTIONAL_IMPL == 1 )
1605 {
1606 // Using an auto stub taking the lambda first, then assign to explicit template typed function<R(A...)>
1607 // Notable: While the `auto stub` is TriviallyCopyable, the delegated jau::func::ylambda_target_t::data_type is not.
1608 // However, direct assignment in the next example is all TriviallyCopyable and hence efficient.
1609 auto stub = [](auto& self, int x) -> int {
1610 if( 0 == x ) {
1611 return 1;
1612 } else {
1613 return x * self(x-1);
1614 }
1615 };
1616 typedef decltype(stub) stub_type;
1618
1619 function<int(int)> f_1( jau::func::ylambda_target_t<int, stub_type, int>::delegate(stub), 0 );
1620
1621 fprintf(stderr, "ylambda 1 f_1: %s\n", f_1.toString().c_str());
1622 REQUIRE( jau::func::target_type::ylambda == f_1.type() );
1623 REQUIRE( 24 == f_1(4) );
1624 }
1625 {
1626 function<int(int)> f_1 = function<int(int)>::bind_ylambda( [](function<int(int)>::delegate_type& self, int x) -> int {
1627 if( 0 == x ) {
1628 return 1;
1629 } else {
1630 return x * self(x-1);
1631 }
1632 } );
1633
1634 fprintf(stderr, "ylambda 3 f_1: %s\n", f_1.toString().c_str());
1635 REQUIRE( jau::func::target_type::ylambda == f_1.type() );
1636 REQUIRE( 24 == f_1(4) ); // `self` is bound to function<R(A...)>::delegate_type `f_1.target`, `x` is 4
1637 }
1638#endif
1639 }
1640
1642 // std::function
1643 {
1644 std::function<int(int i)> f = [](int i)->int {
1645 int res = i+100;
1646 return res;;
1647 };
1648
1649 REQUIRE( true == static_cast<bool>( f ) );
1650 REQUIRE( nullptr != f );
1651 REQUIRE( f != nullptr );
1652 }
1653 {
1654 std::function<int(int i)> f;
1655
1656 REQUIRE( false == static_cast<bool>( f ) );
1657 REQUIRE( nullptr == f );
1658 REQUIRE( f == nullptr );
1659 }
1660
1661 // jau::function
1662#if ( FUNCTIONAL_IMPL == 1 )
1663 {
1664 jau::function<int(int i)> f = [](int i)->int {
1665 int res = i+100;
1666 return res;;
1667 };
1668
1669 REQUIRE( true == static_cast<bool>( f ) );
1670 REQUIRE( nullptr != f );
1671 REQUIRE( f != nullptr );
1672 }
1673 {
1674 jau::function<int(int i)> f;
1675
1676 REQUIRE( false == static_cast<bool>( f ) );
1677 REQUIRE( nullptr == f );
1678 REQUIRE( f == nullptr );
1679 }
1680#endif
1681 }
1682
1684 // std::function
1685 {
1686 std::function<int(TrivialObj i)> f = [](TrivialObj i)->int {
1687 int res = i.i1()+i.i2()+100;
1688 return res;;
1689 };
1690
1691 REQUIRE( true == static_cast<bool>( f ) );
1692 REQUIRE( nullptr != f );
1693 REQUIRE( f != nullptr );
1694 REQUIRE( 103 == f(TrivialObj()) );
1695 }
1696 {
1697 // Test null
1698 {
1699 function<int(TrivialObj)> fa0;
1700 function<int(TrivialObj)> fa1 = nullptr;
1701 REQUIRE( jau::func::target_type::null == fa0.type() );
1702 REQUIRE( jau::func::target_type::null == fa1.type() );
1703 }
1704 {
1705 typedef jau::function<bool(TrivialObj /* data */, bool /* is_final */)> SomeFunc;
1706 SomeFunc fa0;
1707 SomeFunc fa1 = nullptr;
1708 REQUIRE( jau::func::target_type::null == fa0.type() );
1709 REQUIRE( jau::func::target_type::null == fa1.type() );
1710 }
1711 }
1712 {
1713 // Test capturing lambdas
1714 volatile int i = 100;
1715
1716 function<int(TrivialObj i)> fa0 = [](TrivialObj o)->int {
1717 int res = o.i1()+o.i2()+100;
1718 return res;;
1719 };
1720 fprintf(stderr, "lambda.0: %s, signature %s\n", fa0.toString().c_str(), fa0.signature().internal_name());
1721 REQUIRE( jau::func::target_type::lambda == fa0.type() );
1722 REQUIRE(103 == fa0(TrivialObj()));
1723
1724 auto fa2_stub = [&](TrivialObj a) -> int {
1725 return i + a.i1() + a.i2();
1726 };
1727 function<int(TrivialObj)> fa2_a = fa2_stub;
1728 fprintf(stderr, "lambda.2_a: %s, signature %s\n", fa2_a.toString().c_str(), fa2_a.signature().internal_name());
1729 REQUIRE( jau::func::target_type::lambda == fa2_a.type() );
1730 REQUIRE(103 == fa2_a(TrivialObj()));
1731
1732 function<int(TrivialObj)> fa2_b = fa2_stub;
1733 fprintf(stderr, "lambda.2_b: %s, signature %s\n", fa2_b.toString().c_str(), fa2_b.signature().internal_name());
1734 REQUIRE( jau::func::target_type::lambda == fa2_b.type() );
1735 REQUIRE(103 == fa2_b(TrivialObj()));
1736 }
1737 {
1738 // free, result non-void
1739 typedef int(*cfunc)(TrivialObj); // to force non-capturing lambda into a free function template type deduction
1740 function<int(TrivialObj)> fl_0 = (cfunc) ( [](TrivialObj i) -> int {
1741 int res = i.i1()+i.i2()+100;
1742 return res;
1743 } );
1744 fprintf(stderr, "freeB.0 %s\n", fl_0.toString().c_str());
1745 REQUIRE( jau::func::target_type::free == fl_0.type() );
1746 REQUIRE(103 == fl_0(TrivialObj()));
1747 }
1748 }
1750 NonTrivialObj nto0;
1751
1752 // std::function
1753 {
1754 std::function<int(const NonTrivialObj & i)> f = [](const NonTrivialObj &i)->int {
1755 int res = i.i1()+i.i2()+100;
1756 return res;;
1757 };
1758
1759 REQUIRE( true == static_cast<bool>( f ) );
1760 REQUIRE( nullptr != f );
1761 REQUIRE( f != nullptr );
1762 REQUIRE( 103 == f(nto0) );
1763 }
1764 {
1765 // Test null
1766 {
1767 function<int(const NonTrivialObj &)> fa0;
1768 function<int(const NonTrivialObj &)> fa1 = nullptr;
1769 REQUIRE( jau::func::target_type::null == fa0.type() );
1770 REQUIRE( jau::func::target_type::null == fa1.type() );
1771 }
1772 {
1773 typedef jau::function<bool(const NonTrivialObj & /* data */, bool /* is_final */)> SomeFunc;
1774 SomeFunc fa0;
1775 SomeFunc fa1 = nullptr;
1776 REQUIRE( jau::func::target_type::null == fa0.type() );
1777 REQUIRE( jau::func::target_type::null == fa1.type() );
1778 }
1779 }
1780 {
1781 // Test capturing lambdas
1782 volatile int i = 100;
1783
1784 function<int(const NonTrivialObj &)> fa0 = [](const NonTrivialObj & o)->int {
1785 int res = o.i1()+o.i2()+100;
1786 return res;;
1787 };
1788 fprintf(stderr, "lambda.0: %s, signature %s\n", fa0.toString().c_str(), fa0.signature().internal_name());
1789 REQUIRE( jau::func::target_type::lambda == fa0.type() );
1790 REQUIRE(103 == fa0(nto0));
1791
1792 auto fa2_stub = [&](const NonTrivialObj & a) -> int {
1793 return i + a.i1() + a.i2();
1794 };
1795 function<int(const NonTrivialObj &)> fa2_a = fa2_stub;
1796 fprintf(stderr, "lambda.2_a: %s, signature %s\n", fa2_a.toString().c_str(), fa2_a.signature().internal_name());
1797 REQUIRE( jau::func::target_type::lambda == fa2_a.type() );
1798 REQUIRE(103 == fa2_a(nto0));
1799
1800 function<int(const NonTrivialObj &)> fa2_b = fa2_stub;
1801 fprintf(stderr, "lambda.2_b: %s, signature %s\n", fa2_b.toString().c_str(), fa2_b.signature().internal_name());
1802 REQUIRE( jau::func::target_type::lambda == fa2_b.type() );
1803 REQUIRE(103 == fa2_b(nto0));
1804 }
1805 {
1806 // free, result non-void
1807 typedef int(*cfunc)(const NonTrivialObj &); // to force non-capturing lambda into a free function template type deduction
1808 function<int(const NonTrivialObj &)> fl_0 = (cfunc) ( [](const NonTrivialObj & i) -> int {
1809 int res = i.i1()+i.i2()+100;
1810 return res;
1811 } );
1812 fprintf(stderr, "freeB.0 %s\n", fl_0.toString().c_str());
1813 REQUIRE( jau::func::target_type::free == fl_0.type() );
1814 REQUIRE(103 == fl_0(nto0));
1815 }
1816 }
1817
1818 private:
1819
1820 // template<typename R, typename... A>
1821 typedef int(*MyCFunc0)(int);
1822 typedef function<int(int)> MyClassFunction0;
1823
1824 int func02a_member(int i) {
1825 int res = i+100;
1826 return res;;
1827 }
1828 int func02b_member(int i) noexcept {
1829 int res = i+1000;
1830 return res;
1831 }
1832 static int Func03a_static(int i) {
1833 int res = i+100;
1834 return res;
1835 }
1836 static int Func03b_static(int i) noexcept {
1837 int res = i+1000;
1838 return res;
1839 }
1840
1841 typedef function<void(int&, int)> MyClassFunction1;
1842
1843 void func12a_member(int& r, const int i) {
1844 r = i+100;
1845 }
1846 void func12b_member(int& r, const int i) noexcept {
1847 r = i+1000;
1848 }
1849 static void Func13a_static(int& r, const int i) {
1850 r = i+100;
1851 }
1852 static void Func13b_static(int& r, const int i) noexcept {
1853 r = i+1000;
1854 }
1855
1856 typedef function<void()> MyClassFunction2;
1857
1858 void func20a_member() {
1859 // nop
1860 }
1861 static void Func20a_static() {
1862 // nop
1863 }
1864
1865 void test_function0_result_type(const std::string& msg, bool expEqual, const int value, int expRes, MyClassFunction0& f1, MyClassFunction0& f2) {
1866 // test std::function identity
1867 INFO(msg+": Func0.rt Func f1p == f2p : " + std::to_string( f1 == f2 ) + ", f1p: " + f1.toString() + ", f2 "+f2.toString() );
1868 int f1r = f1(value);
1869 int f2r = f2(value);
1870 INFO(msg+": Func0.rt Res_ f1r == f2r : " + std::to_string( f1r == f2r ) + ", f1r: " + std::to_string( f1r ) + ", f2r "+std::to_string( f2r ) );
1871 if( expEqual ) {
1872 REQUIRE(f1r == expRes);
1873 REQUIRE(f2r == expRes);
1874 REQUIRE(f1 == f2);
1875 } else {
1876 REQUIRE(f1 != f2);
1877 }
1878 }
1879 void test_function0________type(const std::string& msg, bool expEqual, MyClassFunction0& f1, MyClassFunction0& f2) {
1880 // test std::function identity
1881 INFO(msg+": Func0._t Func f1p == f2p : " + std::to_string( f1 == f2 ) + ", f1p: " + f1.toString() + ", f2 "+f2.toString() );
1882 {
1883 int f1r = f1(0);
1884 int f2r = f2(0);
1885 (void)f1r;
1886 (void)f2r;
1887 }
1888 if( expEqual ) {
1889 CHECK(f1 == f2);
1890 } else {
1891 CHECK(f1 != f2);
1892 }
1893 }
1894 void test_function0_result_____(const std::string& msg, const int value, int expRes, MyClassFunction0& f1, MyClassFunction0& f2) {
1895 // test std::function identity
1896 INFO(msg+": Func0.ref.r_ Func f1p == f2p : " + std::to_string( f1 == f2 ) + ", f1p: " + f1.toString() + ", f2 "+f2.toString() );
1897 int f1r = f1(value);
1898 int f2r = f2(value);
1899 INFO(msg+": Func0.ref.r_ Res_ f1r == f2r : " + std::to_string( f1r == f2r ) + ", f1r: " + std::to_string( f1r ) + ", f2r "+std::to_string( f2r ) );
1900 REQUIRE(f1r == expRes);
1901 REQUIRE(f2r == expRes);
1902 }
1903 void test_function0_result_copy(const std::string& msg, const int value, int expRes, MyClassFunction0 f1, MyClassFunction0 f2) {
1904 // test std::function identity
1905 INFO(msg+": Func0.cpy.r_ Func f1p == f2p : " + std::to_string( f1 == f2 ) + ", f1p: " + f1.toString() + ", f2 "+f2.toString() );
1906 int f1r = f1(value);
1907 int f2r = f2(value);
1908 INFO(msg+": Func0.cpy.r_ Res_ f1r == f2r : " + std::to_string( f1r == f2r ) + ", f1r: " + std::to_string( f1r ) + ", f2r "+std::to_string( f2r ) );
1909 REQUIRE(f1r == expRes);
1910 REQUIRE(f2r == expRes);
1911 }
1912
1913 void test_function1_result_type(const std::string& msg, bool expEqual, const int value, int expRes, MyClassFunction1& f1, MyClassFunction1& f2) noexcept {
1914 // test std::function identity
1915 INFO(msg+": Func1.ref.rt Func f1p == f2p : " + std::to_string( f1 == f2 ) + ", f1p: " + f1.toString() + ", f2 "+f2.toString() );
1916 int f1r, f2r;
1917 f1(f1r, value);
1918 f2(f2r, value);
1919 INFO(msg+": Func1.ref.rt Res_ f1r == f2r : " + std::to_string( f1r == f2r ) + ", f1r: " + std::to_string( f1r ) + ", f2r "+std::to_string( f2r ) );
1920 if( expEqual ) {
1921 REQUIRE(f1r == expRes);
1922 REQUIRE(f2r == expRes);
1923 REQUIRE(f1 == f2);
1924 } else {
1925 REQUIRE(f1 != f2);
1926 }
1927 }
1928 void test_function1________type(const std::string& msg, bool expEqual, MyClassFunction1& f1, MyClassFunction1& f2) noexcept {
1929 // test std::function identity
1930 INFO(msg+": Func1.ref._t Func f1p == f2p : " + std::to_string( f1 == f2 ) + ", f1p: " + f1.toString() + ", f2 "+f2.toString() );
1931 {
1932 int f1r, f2r;
1933 f1(f1r, 0);
1934 f2(f2r, 0);
1935 (void)f1r;
1936 (void)f2r;
1937 }
1938 if( expEqual ) {
1939 CHECK(f1 == f2);
1940 } else {
1941 CHECK(f1 != f2);
1942 }
1943 }
1944
1945 void test_function2________type(const std::string& msg, bool expEqual, MyClassFunction2& f1, MyClassFunction2& f2) noexcept {
1946 // test std::function identity
1947 INFO(msg+": Func2.ref._t Func f1p == f2p : " + std::to_string( f1 == f2 ) + ", f1p: " + f1.toString() + ", f2 "+f2.toString() );
1948 {
1949 f1();
1950 f2();
1951 }
1952 if( expEqual ) {
1953 CHECK(f1 == f2);
1954 } else {
1955 CHECK(f1 != f2);
1956 }
1957 }
1958
1959 static MyCFunc0 cfunction_00(jau::type_info& type) {
1960 MyCFunc0 f = (MyCFunc0) ( [](int a) -> int {
1961 return 100 + a;
1962 } );
1963 type = jau::type_info( jau::ctti_name<decltype(f)>() );
1964 return f;
1965 }
1966 static function<int(int)> lambda_01() {
1967 static int i = 100;
1968 function<int(int)> f = [&](int a) -> int {
1969 return i + a;
1970 };
1971 return f;
1972 }
1973 static function<int(int)> lambda_02() {
1974 int i = 100;
1975 function<int(int)> f = [i](int a) -> int {
1976 return i + a;
1977 };
1978 return f;
1979 }
1980
1981 struct IntOffset {
1982 int value;
1983 IntOffset(int v) : value(v) {}
1984
1985 bool operator==(const IntOffset& rhs) const {
1986 if( &rhs == this ) {
1987 return true;
1988 }
1989 return value == rhs.value;
1990 }
1991
1992 bool operator!=(const IntOffset& rhs) const
1993 { return !( *this == rhs ); }
1994
1995 };
1996
1997 struct IntOffset2 {
1998 int value;
1999 IntOffset2(int v) : value(v) {}
2000
2001 IntOffset2(const IntOffset2 &o)
2002 : value(o.value)
2003 {
2004 INFO("IntOffset2::copy_ctor");
2005 }
2006 IntOffset2(IntOffset2 &&o)
2007 : value(std::move(o.value))
2008 {
2009 INFO("IntOffset2::move_ctor");
2010 }
2011 IntOffset2& operator=(const IntOffset2 &o) {
2012 INFO("IntOffset2::copy_assign");
2013 if( &o == this ) {
2014 return *this;
2015 }
2016 value = o.value;
2017 return *this;
2018 }
2019 IntOffset2& operator=(IntOffset2 &&o) noexcept {
2020 INFO("IntOffset2::move_assign");
2021 value = std::move(o.value);
2022 (void)value;
2023 return *this;
2024 }
2025
2026 bool operator==(const IntOffset2& rhs) const {
2027 if( &rhs == this ) {
2028 return true;
2029 }
2030 return value == rhs.value;
2031 }
2032
2033 bool operator!=(const IntOffset2& rhs) const
2034 { return !( *this == rhs ); }
2035
2036 };
2037};
2038
2039
2041
2052
2057
2059
int i2() const noexcept
NonTrivialObj(NonTrivialObj &&o) noexcept
void * handle() const noexcept
NonTrivialObj(const NonTrivialObj &o)
int i1() const noexcept
static constexpr y_combinator_lambda make(L func)
constexpr R operator()(A... args) const
void test00_usage()
Unit test covering most variants of jau::function<R(A...)
int i1() const noexcept
int i2() const noexcept
Class template jau::function is a general-purpose static-polymorphic function wrapper.
Generic type information using either Runtime type information (RTTI) or Compile time type informatio...
static constexpr bool is_valid(const char *signature) noexcept
Returns true if given signature is not nullptr and has a string length > 0, otherwise false.
constexpr const char * internal_name() const noexcept
Returns the type name, compiler implementation specific.
static constexpr const bool limited_lambda_id
Static constexpr boolean indicating whether resulting type_info uniqueness is limited for lambda func...
consteval_cxx20 bool is_rtti_available() noexcept
Returns true if compiled with RTTI available.
Definition type_info.hpp:89
constexpr bool value(const Bool rhs) noexcept
constexpr const char * ctti_name() noexcept
Returns the type name of given type T using template Compile Time Type Information (CTTI) only with s...
jau::function< R(A...)> bind_member(C1 *base, R(C0::*mfunc)(A...)) noexcept
Bind given class instance and non-void member function to an anonymous function using func_member_tar...
jau::function< R(A...)> bind_free(R(*func)(A...)) noexcept
Bind given non-void free-function to an anonymous function using func::free_target_t.
jau::function< R(A...)> bind_std(uint64_t id, std::function< R(A...)> func) noexcept
Bind given non-void std::function to an anonymous function using func::std_target_t.
jau::function< R(A...)> bind_capval(const I &data, R(*func)(I &, A...)) noexcept
Bind given data by copying the captured value and the given non-void function to an anonymous functio...
jau::function< R(A...)> bind_capref(I *data_ptr, R(*func)(I *, A...)) noexcept
Bind given data by passing the captured reference (pointer) to the value and non-void function to an ...
@ null
Denotes a func::null_target_t.
@ lambda
Denotes a func::lambda_target_t.
@ capval
Denotes a func::capval_target_t.
@ capref
Denotes a func::capref_target_t.
@ member
Denotes a func::member_target_t.
@ free
Denotes a func::free_target_t.
@ std
Denotes a func::std_target_t.
@ ylambda
Denotes a func::ylambda_target_t.
__pack(...): Produces MSVC, clang and gcc compatible lead-in and -out macros.
Definition backtrace.hpp:32
Helper, allowing simple access to compile time typename and Type traits information,...
Definition type_cue.hpp:95
static void print(const std::string &typedefname, const TypeTraitGroup verbosity=TypeTraitGroup::NONE)
Print information of this type to stdout, potentially with all Type traits known.
Definition type_cue.hpp:204
static std::string f(uint32_t v)
static void print(const Value_type a)
std::shared_ptr< NonTrivialObj > NonTrivialObjSRef
#define FUNCTIONAL_IMPL
static void Func1a_free(int &r, int i) noexcept
METHOD_AS_TEST_CASE(TestFunction01::test00_usage, "00_usage")
static std::string impl_name
static int Func0a_free(int i) noexcept
static void Func2a_free() noexcept
std::shared_ptr< TrivialObj > TrivialObjSRef