1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9// <functional>
10
11// reference_wrapper
12
13// template <class... ArgTypes>
14// constexpr typename result_of<T&(ArgTypes&&...)>::type // constexpr since C++20
15// operator() (ArgTypes&&...) const
16// noexcept(is_nothrow_invocable_v<T&, ArgTypes...>); // noexcept since C++17
17
18#include <functional>
19#include <cassert>
20
21#include "test_macros.h"
22
23#if TEST_STD_VER > 14
24# define INVOKE_NOEXCEPT(expected, ...) static_assert(noexcept(__VA_ARGS__) == expected)
25#else
26# define INVOKE_NOEXCEPT(expected, ...)
27#endif
28
29int count = 0;
30
31// 1 arg, return void
32
33void f_void_1(int i)
34{
35 count += i;
36}
37
38struct A_void_1
39{
40 void operator()(int i)
41 {
42 count += i;
43 }
44
45 void mem1() {++count;}
46 void mem2() const {++count;}
47};
48
49void
50test_void_1()
51{
52 int save_count = count;
53 // function
54 {
55 std::reference_wrapper<void (int)> r1(f_void_1);
56 int i = 2;
57 r1(i);
58 INVOKE_NOEXCEPT(false, r1(i));
59 assert(count == save_count+2);
60 save_count = count;
61 }
62 // function pointer
63 {
64 void (*fp)(int) = f_void_1;
65 std::reference_wrapper<void (*)(int)> r1(fp);
66 int i = 3;
67 r1(i);
68 INVOKE_NOEXCEPT(false, r1(i));
69 assert(count == save_count+3);
70 save_count = count;
71 }
72 // functor
73 {
74 A_void_1 a0;
75 std::reference_wrapper<A_void_1> r1(a0);
76 int i = 4;
77 r1(i);
78 INVOKE_NOEXCEPT(false, r1(i));
79 assert(count == save_count+4);
80 save_count = count;
81 }
82 // member function pointer
83 {
84 void (A_void_1::*fp)() = &A_void_1::mem1;
85 std::reference_wrapper<void (A_void_1::*)()> r1(fp);
86 A_void_1 a;
87 r1(a);
88 INVOKE_NOEXCEPT(false, r1(a));
89 assert(count == save_count+1);
90 save_count = count;
91 A_void_1* ap = &a;
92 r1(ap);
93 INVOKE_NOEXCEPT(false, r1(ap));
94 assert(count == save_count+1);
95 save_count = count;
96 }
97 // const member function pointer
98 {
99 void (A_void_1::*fp)() const = &A_void_1::mem2;
100 std::reference_wrapper<void (A_void_1::*)() const> r1(fp);
101 A_void_1 a;
102 r1(a);
103 INVOKE_NOEXCEPT(false, r1(a));
104 assert(count == save_count+1);
105 save_count = count;
106 A_void_1* ap = &a;
107 r1(ap);
108 INVOKE_NOEXCEPT(false, r1(ap));
109 assert(count == save_count+1);
110 save_count = count;
111 }
112}
113
114// 1 arg, return int
115
116int f_int_1(int i)
117{
118 return i + 1;
119}
120
121struct A_int_1
122{
123 A_int_1() : data_(5) {}
124 int operator()(int i)
125 {
126 return i - 1;
127 }
128
129 int mem1() {return 3;}
130 int mem2() const {return 4;}
131 int data_;
132};
133
134void
135test_int_1()
136{
137 // function
138 {
139 std::reference_wrapper<int (int)> r1(f_int_1);
140 int i = 2;
141 assert(r1(i) == 3);
142 INVOKE_NOEXCEPT(false, r1(i));
143 }
144 // function pointer
145 {
146 int (*fp)(int) = f_int_1;
147 std::reference_wrapper<int (*)(int)> r1(fp);
148 int i = 3;
149 assert(r1(i) == 4);
150 INVOKE_NOEXCEPT(false, r1(i));
151 }
152 // functor
153 {
154 A_int_1 a0;
155 std::reference_wrapper<A_int_1> r1(a0);
156 int i = 4;
157 assert(r1(i) == 3);
158 INVOKE_NOEXCEPT(false, r1(i));
159 }
160 // member function pointer
161 {
162 int (A_int_1::*fp)() = &A_int_1::mem1;
163 std::reference_wrapper<int (A_int_1::*)()> r1(fp);
164 A_int_1 a;
165 assert(r1(a) == 3);
166 INVOKE_NOEXCEPT(false, r1(a));
167 A_int_1* ap = &a;
168 assert(r1(ap) == 3);
169 INVOKE_NOEXCEPT(false, r1(ap));
170 }
171 // const member function pointer
172 {
173 int (A_int_1::*fp)() const = &A_int_1::mem2;
174 std::reference_wrapper<int (A_int_1::*)() const> r1(fp);
175 A_int_1 a;
176 assert(r1(a) == 4);
177 INVOKE_NOEXCEPT(false, r1(a));
178 A_int_1* ap = &a;
179 assert(r1(ap) == 4);
180 INVOKE_NOEXCEPT(false, r1(ap));
181 }
182 // member data pointer
183 {
184 int A_int_1::*fp = &A_int_1::data_;
185 std::reference_wrapper<int A_int_1::*> r1(fp);
186 A_int_1 a;
187 assert(r1(a) == 5);
188 INVOKE_NOEXCEPT(true, r1(a));
189 r1(a) = 6;
190 assert(r1(a) == 6);
191 A_int_1* ap = &a;
192 assert(r1(ap) == 6);
193 r1(ap) = 7;
194 assert(r1(ap) == 7);
195 INVOKE_NOEXCEPT(true, r1(ap));
196 }
197}
198
199// 2 arg, return void
200
201void f_void_2(int i, int j)
202{
203 count += i+j;
204}
205
206struct A_void_2
207{
208 void operator()(int i, int j)
209 {
210 count += i+j;
211 }
212
213 void mem1(int i) {count += i;}
214 void mem2(int i) const {count += i;}
215};
216
217void
218test_void_2()
219{
220 int save_count = count;
221 // function
222 {
223 std::reference_wrapper<void (int, int)> r1(f_void_2);
224 int i = 2;
225 int j = 3;
226 r1(i, j);
227 INVOKE_NOEXCEPT(false, r1(i, j));
228 assert(count == save_count+5);
229 save_count = count;
230 }
231 // function pointer
232 {
233 void (*fp)(int, int) = f_void_2;
234 std::reference_wrapper<void (*)(int, int)> r1(fp);
235 int i = 3;
236 int j = 4;
237 r1(i, j);
238 INVOKE_NOEXCEPT(false, r1(i, j));
239 assert(count == save_count+7);
240 save_count = count;
241 }
242 // functor
243 {
244 A_void_2 a0;
245 std::reference_wrapper<A_void_2> r1(a0);
246 int i = 4;
247 int j = 5;
248 r1(i, j);
249 INVOKE_NOEXCEPT(false, r1(i, j));
250 assert(count == save_count+9);
251 save_count = count;
252 }
253 // member function pointer
254 {
255 void (A_void_2::*fp)(int) = &A_void_2::mem1;
256 std::reference_wrapper<void (A_void_2::*)(int)> r1(fp);
257 A_void_2 a;
258 int i = 3;
259 r1(a, i);
260 assert(count == save_count+3);
261 save_count = count;
262 A_void_2* ap = &a;
263 r1(ap, i);
264 INVOKE_NOEXCEPT(false, r1(ap, i));
265 assert(count == save_count+3);
266 save_count = count;
267 }
268 // const member function pointer
269 {
270 void (A_void_2::*fp)(int) const = &A_void_2::mem2;
271 std::reference_wrapper<void (A_void_2::*)(int) const> r1(fp);
272 A_void_2 a;
273 int i = 4;
274 r1(a, i);
275 INVOKE_NOEXCEPT(false, r1(a, i));
276 assert(count == save_count+4);
277 save_count = count;
278 A_void_2* ap = &a;
279 r1(ap, i);
280 INVOKE_NOEXCEPT(false, r1(ap, i));
281 assert(count == save_count+4);
282 save_count = count;
283 }
284}
285
286// 2 arg, return int
287
288int f_int_2(int i, int j)
289{
290 return i+j;
291}
292
293struct A_int_2
294{
295 int operator()(int i, int j)
296 {
297 return i+j;
298 }
299
300 int mem1(int i) {return i+1;}
301 int mem2(int i) const {return i+2;}
302};
303
304void
305test_int_2()
306{
307 // function
308 {
309 std::reference_wrapper<int (int, int)> r1(f_int_2);
310 int i = 2;
311 int j = 3;
312 assert(r1(i, j) == i+j);
313 INVOKE_NOEXCEPT(false, r1(i, j));
314 }
315 // function pointer
316 {
317 int (*fp)(int, int) = f_int_2;
318 std::reference_wrapper<int (*)(int, int)> r1(fp);
319 int i = 3;
320 int j = 4;
321 assert(r1(i, j) == i+j);
322 INVOKE_NOEXCEPT(false, r1(i, j));
323 }
324 // functor
325 {
326 A_int_2 a0;
327 std::reference_wrapper<A_int_2> r1(a0);
328 int i = 4;
329 int j = 5;
330 assert(r1(i, j) == i+j);
331 INVOKE_NOEXCEPT(false, r1(i, j));
332 }
333 // member function pointer
334 {
335 int(A_int_2::*fp)(int) = &A_int_2::mem1;
336 std::reference_wrapper<int (A_int_2::*)(int)> r1(fp);
337 A_int_2 a;
338 int i = 3;
339 assert(r1(a, i) == i+1);
340 INVOKE_NOEXCEPT(false, r1(a, i));
341 A_int_2* ap = &a;
342 assert(r1(ap, i) == i+1);
343 INVOKE_NOEXCEPT(false, r1(ap, i));
344 }
345 // const member function pointer
346 {
347 int (A_int_2::*fp)(int) const = &A_int_2::mem2;
348 std::reference_wrapper<int (A_int_2::*)(int) const> r1(fp);
349 A_int_2 a;
350 int i = 4;
351 assert(r1(a, i) == i+2);
352 INVOKE_NOEXCEPT(false, r1(a, i));
353 A_int_2* ap = &a;
354 assert(r1(ap, i) == i+2);
355 INVOKE_NOEXCEPT(false, r1(ap, i));
356 }
357}
358
359#if TEST_STD_VER >= 11
360
361// 1 arg, return void, noexcept
362
363void f_void_1_noexcept(int i) noexcept
364{
365 count += i;
366}
367
368struct A_void_1_noexcept
369{
370 void operator()(int i) noexcept
371 {
372 count += i;
373 }
374
375 void mem1() noexcept {++count;}
376 void mem2() const noexcept {++count;}
377};
378
379void
380test_void_1_noexcept()
381{
382 int save_count = count;
383 // function
384 {
385 std::reference_wrapper<void (int) noexcept> r1(f_void_1_noexcept);
386 int i = 2;
387 r1(i);
388 INVOKE_NOEXCEPT(true, r1(i));
389 assert(count == save_count+2);
390 save_count = count;
391 }
392 // function pointer
393 {
394 void (*fp)(int) noexcept = f_void_1_noexcept;
395 std::reference_wrapper<void (*)(int) noexcept> r1(fp);
396 int i = 3;
397 r1(i);
398 INVOKE_NOEXCEPT(true, r1(i));
399 assert(count == save_count+3);
400 save_count = count;
401 }
402 // functor
403 {
404 A_void_1_noexcept a0;
405 std::reference_wrapper<A_void_1_noexcept> r1(a0);
406 int i = 4;
407 r1(i);
408 INVOKE_NOEXCEPT(true, r1(i));
409 assert(count == save_count+4);
410 save_count = count;
411 }
412 // member function pointer
413 {
414 void (A_void_1_noexcept::*fp)() noexcept = &A_void_1_noexcept::mem1;
415 std::reference_wrapper<void (A_void_1_noexcept::*)() noexcept> r1(fp);
416 A_void_1_noexcept a;
417 r1(a);
418 INVOKE_NOEXCEPT(true, r1(a));
419 assert(count == save_count+1);
420 save_count = count;
421 A_void_1_noexcept* ap = &a;
422 r1(ap);
423 INVOKE_NOEXCEPT(true, r1(ap));
424 assert(count == save_count+1);
425 save_count = count;
426 }
427 // const member function pointer
428 {
429 void (A_void_1_noexcept::*fp)() const noexcept = &A_void_1_noexcept::mem2;
430 std::reference_wrapper<void (A_void_1_noexcept::*)() const noexcept> r1(fp);
431 A_void_1_noexcept a;
432 r1(a);
433 INVOKE_NOEXCEPT(true, r1(a));
434 assert(count == save_count+1);
435 save_count = count;
436 A_void_1_noexcept* ap = &a;
437 r1(ap);
438 INVOKE_NOEXCEPT(true, r1(ap));
439 assert(count == save_count+1);
440 save_count = count;
441 }
442}
443
444// 1 arg, return int, noexcept
445
446int f_int_1_noexcept(int i) noexcept
447{
448 return i + 1;
449}
450
451struct A_int_1_noexcept
452{
453 A_int_1_noexcept() : data_(5) {}
454 int operator()(int i) noexcept
455 {
456 return i - 1;
457 }
458
459 int mem1() noexcept {return 3;}
460 int mem2() const noexcept {return 4;}
461 int data_;
462};
463
464void
465test_int_1_noexcept()
466{
467 // function
468 {
469 std::reference_wrapper<int (int) noexcept> r1(f_int_1_noexcept);
470 int i = 2;
471 assert(r1(i) == 3);
472 INVOKE_NOEXCEPT(true, r1(i));
473 }
474 // function pointer
475 {
476 int (*fp)(int) noexcept = f_int_1_noexcept;
477 std::reference_wrapper<int (*)(int) noexcept> r1(fp);
478 int i = 3;
479 assert(r1(i) == 4);
480 INVOKE_NOEXCEPT(true, r1(i));
481 }
482 // functor
483 {
484 A_int_1_noexcept a0;
485 std::reference_wrapper<A_int_1_noexcept> r1(a0);
486 int i = 4;
487 assert(r1(i) == 3);
488 INVOKE_NOEXCEPT(true, r1(i));
489 }
490 // member function pointer
491 {
492 int (A_int_1_noexcept::*fp)() noexcept = &A_int_1_noexcept::mem1;
493 std::reference_wrapper<int (A_int_1_noexcept::*)() noexcept> r1(fp);
494 A_int_1_noexcept a;
495 assert(r1(a) == 3);
496 INVOKE_NOEXCEPT(true, r1(a));
497 A_int_1_noexcept* ap = &a;
498 assert(r1(ap) == 3);
499 INVOKE_NOEXCEPT(true, r1(ap));
500 }
501 // const member function pointer
502 {
503 int (A_int_1_noexcept::*fp)() const noexcept = &A_int_1_noexcept::mem2;
504 std::reference_wrapper<int (A_int_1_noexcept::*)() const noexcept> r1(fp);
505 A_int_1_noexcept a;
506 assert(r1(a) == 4);
507 INVOKE_NOEXCEPT(true, r1(a));
508 A_int_1_noexcept* ap = &a;
509 assert(r1(ap) == 4);
510 INVOKE_NOEXCEPT(true, r1(ap));
511 }
512 // member data pointer
513 {
514 int A_int_1_noexcept::*fp = &A_int_1_noexcept::data_;
515 std::reference_wrapper<int A_int_1_noexcept::*> r1(fp);
516 A_int_1_noexcept a;
517 assert(r1(a) == 5);
518 INVOKE_NOEXCEPT(true, r1(a));
519 r1(a) = 6;
520 assert(r1(a) == 6);
521 A_int_1_noexcept* ap = &a;
522 assert(r1(ap) == 6);
523 r1(ap) = 7;
524 assert(r1(ap) == 7);
525 INVOKE_NOEXCEPT(true, r1(ap));
526 }
527}
528
529// 2 arg, return void, noexcept
530
531void f_void_2_noexcept(int i, int j) noexcept
532{
533 count += i+j;
534}
535
536struct A_void_2_noexcept
537{
538 void operator()(int i, int j) noexcept
539 {
540 count += i+j;
541 }
542
543 void mem1(int i) noexcept {count += i;}
544 void mem2(int i) const noexcept {count += i;}
545};
546
547void
548test_void_2_noexcept()
549{
550 int save_count = count;
551 // function
552 {
553 std::reference_wrapper<void (int, int) noexcept> r1(f_void_2_noexcept);
554 int i = 2;
555 int j = 3;
556 r1(i, j);
557 INVOKE_NOEXCEPT(true, r1(i, j));
558 assert(count == save_count+5);
559 save_count = count;
560 }
561 // function pointer
562 {
563 void (*fp)(int, int) noexcept = f_void_2_noexcept;
564 std::reference_wrapper<void (*)(int, int) noexcept> r1(fp);
565 int i = 3;
566 int j = 4;
567 r1(i, j);
568 INVOKE_NOEXCEPT(true, r1(i, j));
569 assert(count == save_count+7);
570 save_count = count;
571 }
572 // functor
573 {
574 A_void_2_noexcept a0;
575 std::reference_wrapper<A_void_2_noexcept> r1(a0);
576 int i = 4;
577 int j = 5;
578 r1(i, j);
579 INVOKE_NOEXCEPT(true, r1(i, j));
580 assert(count == save_count+9);
581 save_count = count;
582 }
583 // member function pointer
584 {
585 void (A_void_2_noexcept::*fp)(int) noexcept = &A_void_2_noexcept::mem1;
586 std::reference_wrapper<void (A_void_2_noexcept::*)(int) noexcept> r1(fp);
587 A_void_2_noexcept a;
588 int i = 3;
589 r1(a, i);
590 assert(count == save_count+3);
591 save_count = count;
592 A_void_2_noexcept* ap = &a;
593 r1(ap, i);
594 INVOKE_NOEXCEPT(true, r1(ap, i));
595 assert(count == save_count+3);
596 save_count = count;
597 }
598 // const member function pointer
599 {
600 void (A_void_2_noexcept::*fp)(int) const noexcept = &A_void_2_noexcept::mem2;
601 std::reference_wrapper<void (A_void_2_noexcept::*)(int) const noexcept> r1(fp);
602 A_void_2_noexcept a;
603 int i = 4;
604 r1(a, i);
605 INVOKE_NOEXCEPT(true, r1(a, i));
606 assert(count == save_count+4);
607 save_count = count;
608 A_void_2_noexcept* ap = &a;
609 r1(ap, i);
610 INVOKE_NOEXCEPT(true, r1(ap, i));
611 assert(count == save_count+4);
612 save_count = count;
613 }
614}
615
616// 2 arg, return int, noexcept
617
618int f_int_2_noexcept(int i, int j) noexcept
619{
620 return i+j;
621}
622
623struct A_int_2_noexcept
624{
625 int operator()(int i, int j) noexcept
626 {
627 return i+j;
628 }
629
630 int mem1(int i) noexcept {return i+1;}
631 int mem2(int i) const noexcept {return i+2;}
632};
633
634void
635test_int_2_noexcept()
636{
637 // function
638 {
639 std::reference_wrapper<int (int, int) noexcept> r1(f_int_2_noexcept);
640 int i = 2;
641 int j = 3;
642 assert(r1(i, j) == i+j);
643 INVOKE_NOEXCEPT(true, r1(i, j));
644 }
645 // function pointer
646 {
647 int (*fp)(int, int) noexcept = f_int_2_noexcept;
648 std::reference_wrapper<int (*)(int, int) noexcept> r1(fp);
649 int i = 3;
650 int j = 4;
651 assert(r1(i, j) == i+j);
652 INVOKE_NOEXCEPT(true, r1(i, j));
653 }
654 // functor
655 {
656 A_int_2_noexcept a0;
657 std::reference_wrapper<A_int_2_noexcept> r1(a0);
658 int i = 4;
659 int j = 5;
660 assert(r1(i, j) == i+j);
661 INVOKE_NOEXCEPT(true, r1(i, j));
662 }
663 // member function pointer
664 {
665 int(A_int_2_noexcept::*fp)(int) noexcept = &A_int_2_noexcept::mem1;
666 std::reference_wrapper<int (A_int_2_noexcept::*)(int) noexcept> r1(fp);
667 A_int_2_noexcept a;
668 int i = 3;
669 assert(r1(a, i) == i+1);
670 INVOKE_NOEXCEPT(true, r1(a, i));
671 A_int_2_noexcept* ap = &a;
672 assert(r1(ap, i) == i+1);
673 INVOKE_NOEXCEPT(true, r1(ap, i));
674 }
675 // const member function pointer
676 {
677 int (A_int_2_noexcept::*fp)(int) const noexcept = &A_int_2_noexcept::mem2;
678 std::reference_wrapper<int (A_int_2_noexcept::*)(int) const noexcept> r1(fp);
679 A_int_2_noexcept a;
680 int i = 4;
681 assert(r1(a, i) == i+2);
682 INVOKE_NOEXCEPT(true, r1(a, i));
683 A_int_2_noexcept* ap = &a;
684 assert(r1(ap, i) == i+2);
685 INVOKE_NOEXCEPT(true, r1(ap, i));
686 }
687}
688
689#endif // TEST_STD_VER >= 11
690
691int main(int, char**)
692{
693 test_void_1();
694 test_int_1();
695 test_void_2();
696 test_int_2();
697#if TEST_STD_VER >= 11
698 test_void_1_noexcept();
699 test_int_1_noexcept();
700 test_void_2_noexcept();
701 test_int_2_noexcept();
702#endif // TEST_STD_VER >= 11
703
704 return 0;
705}
706

source code of libcxx/test/std/utilities/function.objects/refwrap/refwrap.invoke/invoke.pass.cpp