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