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