mimic++ v9.2.1
Loading...
Searching...
No Matches
TypeTraits.hpp
Go to the documentation of this file.
1// Copyright Dominic (DNKpp) Koepke 2024 - 2025.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at
4// https://www.boost.org/LICENSE_1_0.txt)
5
6#ifndef MIMICPP_TYPE_TRAITS_HPP
7#define MIMICPP_TYPE_TRAITS_HPP
8
9#pragma once
10
11#include "mimic++/Fwd.hpp"
13
14#ifndef MIMICPP_DETAIL_IS_MODULE
15 #include <concepts>
16 #include <cstddef>
17 #include <cstdint>
18 #include <tuple>
19 #include <type_traits>
20#endif
21
22namespace mimicpp::detail
23{
24 template <typename Signature>
25 struct has_default_call_convention
26 : public std::false_type
27 {
28 };
29
30 template <typename Signature>
31 inline constexpr bool has_default_call_convention_v = has_default_call_convention<Signature>::value;
32
33 template <typename Return, typename... Params>
34 struct has_default_call_convention<Return(Params...)>
35 : public std::true_type
36 {
37 };
38
39 template <typename Return, typename... Params>
40 struct has_default_call_convention<Return(Params..., ...)>
41 : public std::true_type
42 {
43 };
44
45 template <typename Return, typename... Params>
46 struct has_default_call_convention<Return(Params...) noexcept>
47 : public std::true_type
48 {
49 };
50
51 template <typename Return, typename... Params>
52 struct has_default_call_convention<Return(Params..., ...) noexcept>
53 : public std::true_type
54 {
55 };
56
57 template <typename Return, typename... Params>
58 struct has_default_call_convention<Return(Params...) const>
59 : public std::true_type
60 {
61 };
62
63 template <typename Return, typename... Params>
64 struct has_default_call_convention<Return(Params..., ...) const>
65 : public std::true_type
66 {
67 };
68
69 template <typename Return, typename... Params>
70 struct has_default_call_convention<Return(Params...) const noexcept>
71 : public std::true_type
72 {
73 };
74
75 template <typename Return, typename... Params>
76 struct has_default_call_convention<Return(Params..., ...) const noexcept>
77 : public std::true_type
78 {
79 };
80
81 template <typename Return, typename... Params>
82 struct has_default_call_convention<Return(Params...)&>
83 : public std::true_type
84 {
85 };
86
87 template <typename Return, typename... Params>
88 struct has_default_call_convention<Return(Params..., ...)&>
89 : public std::true_type
90 {
91 };
92
93 template <typename Return, typename... Params>
94 struct has_default_call_convention<Return(Params...) & noexcept>
95 : public std::true_type
96 {
97 };
98
99 template <typename Return, typename... Params>
100 struct has_default_call_convention<Return(Params..., ...) & noexcept>
101 : public std::true_type
102 {
103 };
104
105 template <typename Return, typename... Params>
106 struct has_default_call_convention<Return(Params...) const&>
107 : public std::true_type
108 {
109 };
110
111 template <typename Return, typename... Params>
112 struct has_default_call_convention<Return(Params..., ...) const&>
113 : public std::true_type
114 {
115 };
116
117 template <typename Return, typename... Params>
118 struct has_default_call_convention<Return(Params...) const & noexcept>
119 : public std::true_type
120 {
121 };
122
123 template <typename Return, typename... Params>
124 struct has_default_call_convention<Return(Params..., ...) const & noexcept>
125 : public std::true_type
126 {
127 };
128
129 template <typename Return, typename... Params>
130 struct has_default_call_convention<Return(Params...) &&>
131 : public std::true_type
132 {
133 };
134
135 template <typename Return, typename... Params>
136 struct has_default_call_convention<Return(Params..., ...) &&>
137 : public std::true_type
138 {
139 };
140
141 template <typename Return, typename... Params>
142 struct has_default_call_convention<Return(Params...) && noexcept>
143 : public std::true_type
144 {
145 };
146
147 template <typename Return, typename... Params>
148 struct has_default_call_convention<Return(Params..., ...) && noexcept>
149 : public std::true_type
150 {
151 };
152
153 template <typename Return, typename... Params>
154 struct has_default_call_convention<Return(Params...) const&&>
155 : public std::true_type
156 {
157 };
158
159 template <typename Return, typename... Params>
160 struct has_default_call_convention<Return(Params..., ...) const&&>
161 : public std::true_type
162 {
163 };
164
165 template <typename Return, typename... Params>
166 struct has_default_call_convention<Return(Params...) const && noexcept>
167 : public std::true_type
168 {
169 };
170
171 template <typename Return, typename... Params>
172 struct has_default_call_convention<Return(Params..., ...) const && noexcept>
173 : public std::true_type
174 {
175 };
176
177 struct default_call_convention
178 {
179 };
180}
181
183{
189
194 template <typename Signature>
195 concept has_default_call_convention = detail::has_default_call_convention_v<Signature>;
196
205
210 template <has_default_call_convention Signature>
212 {
213 using type = detail::default_call_convention;
214 };
215
219
241
245 template <>
246 struct call_convention_traits<detail::default_call_convention>
247 {
248 using tag_t = detail::default_call_convention;
249
250 template <typename Signature>
251 using remove_call_convention_t = std::type_identity_t<Signature>;
252
253 template <typename Signature>
254 using add_call_convention_t = std::type_identity_t<Signature>;
255
256 template <typename Derived, typename Signature>
257 using call_interface_t = detail::DefaultCallInterface<Derived, Signature>;
258 };
259
263
271
272 template <typename Signature>
274 {
275 using type = typename call_convention_traits<
276 signature_call_convention_t<Signature>>::template remove_call_convention_t<Signature>;
277 };
278
282
283 namespace detail
284 {
285
289 template <
290 typename Signature,
291 template <typename> typename Trait,
293 typename Applied = Trait<typename CallConvTrait::template remove_call_convention_t<Signature>>>
294 struct signature_apply_trait
295 : public std::bool_constant<Applied::value>
296 {
297 using type = typename CallConvTrait::template add_call_convention_t<typename Applied::type>;
298 };
299 }
300
308
309 namespace detail
310 {
311 template <typename Signature>
312 struct signature_remove_noexcept;
313
314 template <typename Return, typename... Params>
315 struct signature_remove_noexcept<Return(Params...)>
316 : public std::false_type
317 {
318 using type = Return(Params...);
319 };
320
321 template <typename Return, typename... Params>
322 struct signature_remove_noexcept<Return(Params..., ...)>
323 : public std::false_type
324 {
325 using type = Return(Params..., ...);
326 };
327
328 template <typename Return, typename... Params>
329 struct signature_remove_noexcept<Return(Params...) noexcept>
330 : public std::true_type
331 {
332 using type = Return(Params...);
333 };
334
335 template <typename Return, typename... Params>
336 struct signature_remove_noexcept<Return(Params..., ...) noexcept>
337 : public std::true_type
338 {
339 using type = Return(Params..., ...);
340 };
341
342 template <typename Return, typename... Params>
343 struct signature_remove_noexcept<Return(Params...) const>
344 : public std::false_type
345 {
346 using type = Return(Params...) const;
347 };
348
349 template <typename Return, typename... Params>
350 struct signature_remove_noexcept<Return(Params..., ...) const>
351 : public std::false_type
352 {
353 using type = Return(Params..., ...) const;
354 };
355
356 template <typename Return, typename... Params>
357 struct signature_remove_noexcept<Return(Params...) const noexcept>
358 : public std::true_type
359 {
360 using type = Return(Params...) const;
361 };
362
363 template <typename Return, typename... Params>
364 struct signature_remove_noexcept<Return(Params..., ...) const noexcept>
365 : public std::true_type
366 {
367 using type = Return(Params..., ...) const;
368 };
369
370 template <typename Return, typename... Params>
371 struct signature_remove_noexcept<Return(Params...)&>
372 : public std::false_type
373 {
374 using type = Return(Params...) &;
375 };
376
377 template <typename Return, typename... Params>
378 struct signature_remove_noexcept<Return(Params..., ...)&>
379 : public std::false_type
380 {
381 using type = Return(Params..., ...) &;
382 };
383
384 template <typename Return, typename... Params>
385 struct signature_remove_noexcept<Return(Params...) & noexcept>
386 : public std::true_type
387 {
388 using type = Return(Params...) &;
389 };
390
391 template <typename Return, typename... Params>
392 struct signature_remove_noexcept<Return(Params..., ...) & noexcept>
393 : public std::true_type
394 {
395 using type = Return(Params..., ...) &;
396 };
397
398 template <typename Return, typename... Params>
399 struct signature_remove_noexcept<Return(Params...) const&>
400 : public std::false_type
401 {
402 using type = Return(Params...) const&;
403 };
404
405 template <typename Return, typename... Params>
406 struct signature_remove_noexcept<Return(Params..., ...) const&>
407 : public std::false_type
408 {
409 using type = Return(Params..., ...) const&;
410 };
411
412 template <typename Return, typename... Params>
413 struct signature_remove_noexcept<Return(Params...) const & noexcept>
414 : public std::true_type
415 {
416 using type = Return(Params...) const&;
417 };
418
419 template <typename Return, typename... Params>
420 struct signature_remove_noexcept<Return(Params..., ...) const & noexcept>
421 : public std::true_type
422 {
423 using type = Return(Params..., ...) const&;
424 };
425
426 template <typename Return, typename... Params>
427 struct signature_remove_noexcept<Return(Params...) &&>
428 : public std::false_type
429 {
430 using type = Return(Params...) &&;
431 };
432
433 template <typename Return, typename... Params>
434 struct signature_remove_noexcept<Return(Params..., ...) &&>
435 : public std::false_type
436 {
437 using type = Return(Params..., ...) &&;
438 };
439
440 template <typename Return, typename... Params>
441 struct signature_remove_noexcept<Return(Params...) && noexcept>
442 : public std::true_type
443 {
444 using type = Return(Params...) &&;
445 };
446
447 template <typename Return, typename... Params>
448 struct signature_remove_noexcept<Return(Params..., ...) && noexcept>
449 : public std::true_type
450 {
451 using type = Return(Params..., ...) &&;
452 };
453
454 template <typename Return, typename... Params>
455 struct signature_remove_noexcept<Return(Params...) const&&>
456 : public std::false_type
457 {
458 using type = Return(Params...) const&&;
459 };
460
461 template <typename Return, typename... Params>
462 struct signature_remove_noexcept<Return(Params..., ...) const&&>
463 : public std::false_type
464 {
465 using type = Return(Params..., ...) const&&;
466 };
467
468 template <typename Return, typename... Params>
469 struct signature_remove_noexcept<Return(Params...) const && noexcept>
470 : public std::true_type
471 {
472 using type = Return(Params...) const&&;
473 };
474
475 template <typename Return, typename... Params>
476 struct signature_remove_noexcept<Return(Params..., ...) const && noexcept>
477 : public std::true_type
478 {
479 using type = Return(Params..., ...) const&&;
480 };
481 }
482
483 template <typename Signature>
485 : public detail::signature_apply_trait<Signature, detail::signature_remove_noexcept>
486 {
487 };
488
492
500
501 namespace detail
502 {
503 template <typename Signature>
505
506 template <typename Signature>
508 struct signature_add_noexcept<Signature>
509 : public std::false_type
510 {
511 using type = Signature;
512 };
513
514 template <typename Return, typename... Params>
515 struct signature_add_noexcept<Return(Params...)>
516 : public std::true_type
517 {
518 using type = Return(Params...) noexcept;
519 };
520
521 template <typename Return, typename... Params>
522 struct signature_add_noexcept<Return(Params..., ...)>
523 : public std::true_type
524 {
525 using type = Return(Params..., ...) noexcept;
526 };
527
528 template <typename Return, typename... Params>
529 struct signature_add_noexcept<Return(Params...) const>
530 : public std::true_type
531 {
532 using type = Return(Params...) const noexcept;
533 };
534
535 template <typename Return, typename... Params>
536 struct signature_add_noexcept<Return(Params..., ...) const>
537 : public std::true_type
538 {
539 using type = Return(Params..., ...) const noexcept;
540 };
541
542 template <typename Return, typename... Params>
543 struct signature_add_noexcept<Return(Params...)&>
544 : public std::true_type
545 {
546 using type = Return(Params...) & noexcept;
547 };
548
549 template <typename Return, typename... Params>
550 struct signature_add_noexcept<Return(Params..., ...)&>
551 : public std::true_type
552 {
553 using type = Return(Params..., ...) & noexcept;
554 };
555
556 template <typename Return, typename... Params>
557 struct signature_add_noexcept<Return(Params...) const&>
558 : public std::true_type
559 {
560 using type = Return(Params...) const& noexcept;
561 };
562
563 template <typename Return, typename... Params>
564 struct signature_add_noexcept<Return(Params..., ...) const&>
565 : public std::true_type
566 {
567 using type = Return(Params..., ...) const& noexcept;
568 };
569
570 template <typename Return, typename... Params>
571 struct signature_add_noexcept<Return(Params...) &&>
572 : public std::true_type
573 {
574 using type = Return(Params...) && noexcept;
575 };
576
577 template <typename Return, typename... Params>
578 struct signature_add_noexcept<Return(Params..., ...) &&>
579 : public std::true_type
580 {
581 using type = Return(Params..., ...) && noexcept;
582 };
583
584 template <typename Return, typename... Params>
585 struct signature_add_noexcept<Return(Params...) const&&>
586 : public std::true_type
587 {
588 using type = Return(Params...) const&& noexcept;
589 };
590
591 template <typename Return, typename... Params>
592 struct signature_add_noexcept<Return(Params..., ...) const&&>
593 : public std::true_type
594 {
595 using type = Return(Params..., ...) const&& noexcept;
596 };
597 }
598
599 template <typename Signature>
601 : public detail::signature_apply_trait<Signature, detail::signature_add_noexcept>
602 {
603 };
604
608
616
617 template <typename Signature>
619 : public std::bool_constant<signature_remove_noexcept<Signature>::value>
620 {
621 };
622
626
634
635 namespace detail
636 {
637 template <typename Signature, bool isNoexcept>
638 struct signature_remove_ref_qualifier_impl;
639
640 template <typename Return, typename... Params, bool isNoexcept>
641 struct signature_remove_ref_qualifier_impl<Return(Params...), isNoexcept>
642 : public std::false_type
643 {
644 using type = Return(Params...) noexcept(isNoexcept);
645 };
646
647 template <typename Return, typename... Params, bool isNoexcept>
648 struct signature_remove_ref_qualifier_impl<Return(Params..., ...), isNoexcept>
649 : public std::false_type
650 {
651 using type = Return(Params..., ...) noexcept(isNoexcept);
652 };
653
654 template <typename Return, typename... Params, bool isNoexcept>
655 struct signature_remove_ref_qualifier_impl<Return(Params...) const, isNoexcept>
656 : public std::false_type
657 {
658 using type = Return(Params...) const noexcept(isNoexcept);
659 };
660
661 template <typename Return, typename... Params, bool isNoexcept>
662 struct signature_remove_ref_qualifier_impl<Return(Params..., ...) const, isNoexcept>
663 : public std::false_type
664 {
665 using type = Return(Params..., ...) const noexcept(isNoexcept);
666 };
667
668 template <typename Return, typename... Params, bool isNoexcept>
669 struct signature_remove_ref_qualifier_impl<Return(Params...)&, isNoexcept>
670 : public std::true_type
671 {
672 using type = Return(Params...) noexcept(isNoexcept);
673 };
674
675 template <typename Return, typename... Params, bool isNoexcept>
676 struct signature_remove_ref_qualifier_impl<Return(Params..., ...)&, isNoexcept>
677 : public std::true_type
678 {
679 using type = Return(Params..., ...) noexcept(isNoexcept);
680 };
681
682 template <typename Return, typename... Params, bool isNoexcept>
683 struct signature_remove_ref_qualifier_impl<Return(Params...) const&, isNoexcept>
684 : public std::true_type
685 {
686 using type = Return(Params...) const noexcept(isNoexcept);
687 };
688
689 template <typename Return, typename... Params, bool isNoexcept>
690 struct signature_remove_ref_qualifier_impl<Return(Params..., ...) const&, isNoexcept>
691 : public std::true_type
692 {
693 using type = Return(Params..., ...) const noexcept(isNoexcept);
694 };
695
696 template <typename Return, typename... Params, bool isNoexcept>
697 struct signature_remove_ref_qualifier_impl<Return(Params...)&&, isNoexcept>
698 : public std::true_type
699 {
700 using type = Return(Params...) noexcept(isNoexcept);
701 };
702
703 template <typename Return, typename... Params, bool isNoexcept>
704 struct signature_remove_ref_qualifier_impl<Return(Params..., ...)&&, isNoexcept>
705 : public std::true_type
706 {
707 using type = Return(Params..., ...) noexcept(isNoexcept);
708 };
709
710 template <typename Return, typename... Params, bool isNoexcept>
711 struct signature_remove_ref_qualifier_impl<Return(Params...) const&&, isNoexcept>
712 : public std::true_type
713 {
714 using type = Return(Params...) const noexcept(isNoexcept);
715 };
716
717 template <typename Return, typename... Params, bool isNoexcept>
718 struct signature_remove_ref_qualifier_impl<Return(Params..., ...) const&&, isNoexcept>
719 : public std::true_type
720 {
721 using type = Return(Params..., ...) const noexcept(isNoexcept);
722 };
723
724 // Todo: When msvc some day supports deducing noexcept, we can further simplify this.
725 template <typename Signature, typename Trait = signature_remove_noexcept<Signature>>
726 struct signature_remove_ref_qualifier_
727 : public signature_remove_ref_qualifier_impl<typename Trait::type, Trait::value>
728 {
729 };
730
731 template <typename Signature>
732 using signature_remove_ref_qualifier = signature_remove_ref_qualifier_<Signature>;
733 }
734
735 template <typename Signature>
737 : public detail::signature_apply_trait<Signature, detail::signature_remove_ref_qualifier>
738 {
739 };
740
744
752
753 namespace detail
754 {
755 template <typename Signature, bool isNoexcept>
756 struct signature_remove_const_qualifier_impl;
757
758 template <typename Return, typename... Params, bool isNoexcept>
759 struct signature_remove_const_qualifier_impl<Return(Params...), isNoexcept>
760 : public std::false_type
761 {
762 using type = Return(Params...) noexcept(isNoexcept);
763 };
764
765 template <typename Return, typename... Params, bool isNoexcept>
766 struct signature_remove_const_qualifier_impl<Return(Params...) const, isNoexcept>
767 : public std::true_type
768 {
769 using type = Return(Params...) noexcept(isNoexcept);
770 };
771
772 template <typename Return, typename... Params, bool isNoexcept>
773 struct signature_remove_const_qualifier_impl<Return(Params..., ...), isNoexcept>
774 : public std::false_type
775 {
776 using type = Return(Params..., ...) noexcept(isNoexcept);
777 };
778
779 template <typename Return, typename... Params, bool isNoexcept>
780 struct signature_remove_const_qualifier_impl<Return(Params..., ...) const, isNoexcept>
781 : public std::true_type
782 {
783 using type = Return(Params..., ...) noexcept(isNoexcept);
784 };
785
786 template <typename Return, typename... Params, bool isNoexcept>
787 struct signature_remove_const_qualifier_impl<Return(Params...)&, isNoexcept>
788 : public std::false_type
789 {
790 using type = Return(Params...) & noexcept(isNoexcept);
791 };
792
793 template <typename Return, typename... Params, bool isNoexcept>
794 struct signature_remove_const_qualifier_impl<Return(Params...) const&, isNoexcept>
795 : public std::true_type
796 {
797 using type = Return(Params...) & noexcept(isNoexcept);
798 };
799
800 template <typename Return, typename... Params, bool isNoexcept>
801 struct signature_remove_const_qualifier_impl<Return(Params..., ...)&, isNoexcept>
802 : public std::false_type
803 {
804 using type = Return(Params..., ...) & noexcept(isNoexcept);
805 };
806
807 template <typename Return, typename... Params, bool isNoexcept>
808 struct signature_remove_const_qualifier_impl<Return(Params..., ...) const&, isNoexcept>
809 : public std::true_type
810 {
811 using type = Return(Params..., ...) & noexcept(isNoexcept);
812 };
813
814 template <typename Return, typename... Params, bool isNoexcept>
815 struct signature_remove_const_qualifier_impl<Return(Params...)&&, isNoexcept>
816 : public std::false_type
817 {
818 using type = Return(Params...) && noexcept(isNoexcept);
819 };
820
821 template <typename Return, typename... Params, bool isNoexcept>
822 struct signature_remove_const_qualifier_impl<Return(Params...) const&&, isNoexcept>
823 : public std::true_type
824 {
825 using type = Return(Params...) && noexcept(isNoexcept);
826 };
827
828 template <typename Return, typename... Params, bool isNoexcept>
829 struct signature_remove_const_qualifier_impl<Return(Params..., ...)&&, isNoexcept>
830 : public std::false_type
831 {
832 using type = Return(Params..., ...) && noexcept(isNoexcept);
833 };
834
835 template <typename Return, typename... Params, bool isNoexcept>
836 struct signature_remove_const_qualifier_impl<Return(Params..., ...) const&&, isNoexcept>
837 : public std::true_type
838 {
839 using type = Return(Params..., ...) && noexcept(isNoexcept);
840 };
841
842 // Todo: When msvc some day supports deducing noexcept, we can further simplify this.
843 template <typename Signature, typename Trait = signature_remove_noexcept<Signature>>
844 struct signature_remove_const_qualifier_
845 : public signature_remove_const_qualifier_impl<typename Trait::type, Trait::value>
846 {
847 };
848
849 template <typename Signature>
850 using signature_remove_const_qualifier = signature_remove_const_qualifier_<Signature>;
851 }
852
853 template <typename Signature>
855 : public detail::signature_apply_trait<Signature, detail::signature_remove_const_qualifier>
856 {
857 };
858
862
870
871 namespace detail
872 {
873 template <typename Signature, bool isNoexcept>
874 struct signature_add_const_qualifier_impl;
875
876 template <typename Return, typename... Params, bool isNoexcept>
877 struct signature_add_const_qualifier_impl<Return(Params...), isNoexcept>
878 : public std::true_type
879 {
880 using type = Return(Params...) const noexcept(isNoexcept);
881 };
882
883 template <typename Return, typename... Params, bool isNoexcept>
884 struct signature_add_const_qualifier_impl<Return(Params..., ...), isNoexcept>
885 : public std::true_type
886 {
887 using type = Return(Params..., ...) const noexcept(isNoexcept);
888 };
889
890 template <typename Return, typename... Params, bool isNoexcept>
891 struct signature_add_const_qualifier_impl<Return(Params...)&, isNoexcept>
892 : public std::true_type
893 {
894 using type = Return(Params...) const& noexcept(isNoexcept);
895 };
896
897 template <typename Return, typename... Params, bool isNoexcept>
898 struct signature_add_const_qualifier_impl<Return(Params..., ...)&, isNoexcept>
899 : public std::true_type
900 {
901 using type = Return(Params..., ...) const& noexcept(isNoexcept);
902 };
903
904 template <typename Return, typename... Params, bool isNoexcept>
905 struct signature_add_const_qualifier_impl<Return(Params...)&&, isNoexcept>
906 : public std::true_type
907 {
908 using type = Return(Params...) const&& noexcept(isNoexcept);
909 };
910
911 template <typename Return, typename... Params, bool isNoexcept>
912 struct signature_add_const_qualifier_impl<Return(Params..., ...)&&, isNoexcept>
913 : public std::true_type
914 {
915 using type = Return(Params..., ...) const&& noexcept(isNoexcept);
916 };
917
918 // Todo: When msvc some day supports deducing noexcept, we can further simplify this.
919 template <typename Signature, typename Trait = signature_remove_noexcept<Signature>>
920 struct signature_add_const_qualifier_
921 : public signature_add_const_qualifier_impl<typename Trait::type, Trait::value>
922 {
923 };
924
925 template <typename Signature>
926 requires signature_remove_const_qualifier<Signature>::value
927 struct signature_add_const_qualifier_<Signature>
928 : public std::false_type
929 {
930 using type = Signature;
931 };
932
933 template <typename Signature>
934 using signature_add_const_qualifier = signature_add_const_qualifier_<Signature>;
935 }
936
937 template <typename Signature>
939 : public detail::signature_apply_trait<Signature, detail::signature_add_const_qualifier>
940 {
941 };
942
946
955
956 namespace detail
957 {
958 template <typename Signature, bool isNoexcept>
959 struct signature_add_lvalue_ref_qualifier_impl;
960
961 template <typename Return, typename... Params, bool isNoexcept>
962 struct signature_add_lvalue_ref_qualifier_impl<Return(Params...), isNoexcept>
963 : public std::true_type
964 {
965 using type = Return(Params...) & noexcept(isNoexcept);
966 };
967
968 template <typename Return, typename... Params, bool isNoexcept>
969 struct signature_add_lvalue_ref_qualifier_impl<Return(Params..., ...), isNoexcept>
970 : public std::true_type
971 {
972 using type = Return(Params..., ...) & noexcept(isNoexcept);
973 };
974
975 template <typename Return, typename... Params, bool isNoexcept>
976 struct signature_add_lvalue_ref_qualifier_impl<Return(Params...) const, isNoexcept>
977 : public std::true_type
978 {
979 using type = Return(Params...) const& noexcept(isNoexcept);
980 };
981
982 template <typename Return, typename... Params, bool isNoexcept>
983 struct signature_add_lvalue_ref_qualifier_impl<Return(Params..., ...) const, isNoexcept>
984 : public std::true_type
985 {
986 using type = Return(Params..., ...) const& noexcept(isNoexcept);
987 };
988
989 template <typename Return, typename... Params, bool isNoexcept>
990 struct signature_add_lvalue_ref_qualifier_impl<Return(Params...)&, isNoexcept>
991 : public std::false_type
992 {
993 using type = Return(Params...) & noexcept(isNoexcept);
994 };
995
996 template <typename Return, typename... Params, bool isNoexcept>
997 struct signature_add_lvalue_ref_qualifier_impl<Return(Params..., ...)&, isNoexcept>
998 : public std::false_type
999 {
1000 using type = Return(Params..., ...) & noexcept(isNoexcept);
1001 };
1002
1003 template <typename Return, typename... Params, bool isNoexcept>
1004 struct signature_add_lvalue_ref_qualifier_impl<Return(Params...) const&, isNoexcept>
1005 : public std::false_type
1006 {
1007 using type = Return(Params...) const& noexcept(isNoexcept);
1008 };
1009
1010 template <typename Return, typename... Params, bool isNoexcept>
1011 struct signature_add_lvalue_ref_qualifier_impl<Return(Params..., ...) const&, isNoexcept>
1012 : public std::false_type
1013 {
1014 using type = Return(Params..., ...) const& noexcept(isNoexcept);
1015 };
1016
1017 // Todo: When msvc some day supports deducing noexcept, we can further simplify this.
1018 template <typename Signature, typename Trait = signature_remove_noexcept<Signature>>
1019 struct signature_add_lvalue_ref_qualifier_
1020 : public signature_add_lvalue_ref_qualifier_impl<typename Trait::type, Trait::value>
1021 {
1022 };
1023
1024 template <typename Signature>
1025 using signature_add_lvalue_ref_qualifier = signature_add_lvalue_ref_qualifier_<Signature>;
1026 }
1027
1028 template <typename Signature>
1030 : public detail::signature_apply_trait<Signature, detail::signature_add_lvalue_ref_qualifier>
1031 {
1032 };
1033
1037
1046
1047 namespace detail
1048 {
1049 template <typename Signature, bool isNoexcept>
1050 struct signature_add_rvalue_ref_qualifier_impl;
1051
1052 template <typename Return, typename... Params, bool isNoexcept>
1053 struct signature_add_rvalue_ref_qualifier_impl<Return(Params...), isNoexcept>
1054 : public std::true_type
1055 {
1056 using type = Return(Params...) && noexcept(isNoexcept);
1057 };
1058
1059 template <typename Return, typename... Params, bool isNoexcept>
1060 struct signature_add_rvalue_ref_qualifier_impl<Return(Params..., ...), isNoexcept>
1061 : public std::true_type
1062 {
1063 using type = Return(Params..., ...) && noexcept(isNoexcept);
1064 };
1065
1066 template <typename Return, typename... Params, bool isNoexcept>
1067 struct signature_add_rvalue_ref_qualifier_impl<Return(Params...) const, isNoexcept>
1068 : public std::true_type
1069 {
1070 using type = Return(Params...) const&& noexcept(isNoexcept);
1071 };
1072
1073 template <typename Return, typename... Params, bool isNoexcept>
1074 struct signature_add_rvalue_ref_qualifier_impl<Return(Params..., ...) const, isNoexcept>
1075 : public std::true_type
1076 {
1077 using type = Return(Params..., ...) const&& noexcept(isNoexcept);
1078 };
1079
1080 template <typename Return, typename... Params, bool isNoexcept>
1081 struct signature_add_rvalue_ref_qualifier_impl<Return(Params...)&&, isNoexcept>
1082 : public std::false_type
1083 {
1084 using type = Return(Params...) && noexcept(isNoexcept);
1085 };
1086
1087 template <typename Return, typename... Params, bool isNoexcept>
1088 struct signature_add_rvalue_ref_qualifier_impl<Return(Params..., ...)&&, isNoexcept>
1089 : public std::false_type
1090 {
1091 using type = Return(Params..., ...) && noexcept(isNoexcept);
1092 };
1093
1094 template <typename Return, typename... Params, bool isNoexcept>
1095 struct signature_add_rvalue_ref_qualifier_impl<Return(Params...) const&&, isNoexcept>
1096 : public std::false_type
1097 {
1098 using type = Return(Params...) const&& noexcept(isNoexcept);
1099 };
1100
1101 template <typename Return, typename... Params, bool isNoexcept>
1102 struct signature_add_rvalue_ref_qualifier_impl<Return(Params..., ...) const&&, isNoexcept>
1103 : public std::false_type
1104 {
1105 using type = Return(Params..., ...) const&& noexcept(isNoexcept);
1106 };
1107
1108 // Todo: When msvc some day supports deducing noexcept, we can further simplify this.
1109 template <typename Signature, typename Trait = signature_remove_noexcept<Signature>>
1110 struct signature_add_rvalue_ref_qualifier_
1111 : public signature_add_rvalue_ref_qualifier_impl<typename Trait::type, Trait::value>
1112 {
1113 };
1114
1115 template <typename Signature>
1116 using signature_add_rvalue_ref_qualifier = signature_add_rvalue_ref_qualifier_<Signature>;
1117 }
1118
1119 template <typename Signature>
1121 : public detail::signature_apply_trait<Signature, detail::signature_add_rvalue_ref_qualifier>
1122 {
1123 };
1124
1128
1136
1137 template <typename Signature>
1139 {
1140 using type =
1141 typename detail::signature_remove_ref_qualifier_impl<
1142 typename detail::signature_remove_const_qualifier_impl<
1143 typename detail::signature_remove_noexcept<
1145 false>::type,
1146 false>::type;
1147 };
1148
1152
1160
1161 template <typename Signature>
1164 : public signature_return_type<signature_decay_t<Signature>>
1166 {
1167 };
1168
1169 template <typename Return, typename... Params>
1170 struct signature_return_type<Return(Params...)>
1171 {
1172 using type = Return;
1173 };
1174
1175 template <typename Return, typename... Params>
1176 struct signature_return_type<Return(Params..., ...)>
1177 {
1178 using type = Return;
1179 };
1180
1184
1192
1193 template <std::size_t index, typename Signature>
1196 : public signature_param_type<
1197 index,
1198 signature_decay_t<Signature>>
1200 {
1201 };
1202
1203 template <std::size_t index, typename Return, typename... Params>
1204 struct signature_param_type<index, Return(Params...)>
1205 : public std::tuple_element<index, std::tuple<Params...>>
1206 {
1207 };
1208
1212
1220
1221 template <typename Signature>
1223 : public std::integral_constant<
1224 Constness,
1225 signature_remove_const_qualifier<Signature>::value
1226 ? Constness::as_const
1227 : Constness::non_const>
1228 {
1229 };
1230
1234
1242
1243 template <typename Signature>
1247 signature_remove_noexcept_t<
1248 signature_remove_const_qualifier_t<
1249 signature_remove_call_convention_t<Signature>>>>
1251 {
1252 };
1253
1254 template <typename Return, typename... Params>
1255 struct signature_ref_qualification<Return(Params...)>
1256 : public std::integral_constant<
1257 ValueCategory,
1258 ValueCategory::any>
1259 {
1260 };
1261
1262 template <typename Return, typename... Params>
1263 struct signature_ref_qualification<Return(Params..., ...)>
1264 : public std::integral_constant<
1265 ValueCategory,
1266 ValueCategory::any>
1267 {
1268 };
1269
1270 template <typename Return, typename... Params>
1271 struct signature_ref_qualification<Return(Params...)&>
1272 : public std::integral_constant<
1275 {
1276 };
1277
1278 template <typename Return, typename... Params>
1279 struct signature_ref_qualification<Return(Params..., ...)&>
1280 : public std::integral_constant<
1283 {
1284 };
1285
1286 template <typename Return, typename... Params>
1287 struct signature_ref_qualification<Return(Params...) &&>
1288 : public std::integral_constant<
1291 {
1292 };
1293
1294 template <typename Return, typename... Params>
1295 struct signature_ref_qualification<Return(Params..., ...) &&>
1296 : public std::integral_constant<
1299 {
1300 };
1301
1305
1313
1314 template <typename Signature>
1317 : public signature_param_list<
1318 signature_decay_t<Signature>>
1320 {
1321 };
1322
1323 template <typename Return, typename... Params>
1324 struct signature_param_list<Return(Params...)>
1325 {
1326 using type = util::type_list<Params...>;
1327 };
1328
1332
1340
1341 namespace detail
1342 {
1343 template <typename Signature, typename T, bool isNoexcept>
1344 struct signature_prepend_param_impl;
1345
1346 template <typename Return, typename... Params, typename T, bool isNoexcept>
1347 struct signature_prepend_param_impl<Return(Params...), T, isNoexcept>
1348 : public std::true_type
1349 {
1350 using type = Return(T, Params...) noexcept(isNoexcept);
1351 };
1352
1353 template <typename Return, typename... Params, typename T, bool isNoexcept>
1354 struct signature_prepend_param_impl<Return(Params..., ...), T, isNoexcept>
1355 : public std::true_type
1356 {
1357 using type = Return(T, Params..., ...) noexcept(isNoexcept);
1358 };
1359
1360 template <typename Return, typename... Params, typename T, bool isNoexcept>
1361 struct signature_prepend_param_impl<Return(Params...)&, T, isNoexcept>
1362 : public std::true_type
1363 {
1364 using type = Return(T, Params...) & noexcept(isNoexcept);
1365 };
1366
1367 template <typename Return, typename... Params, typename T, bool isNoexcept>
1368 struct signature_prepend_param_impl<Return(Params..., ...)&, T, isNoexcept>
1369 : public std::true_type
1370 {
1371 using type = Return(T, Params..., ...) & noexcept(isNoexcept);
1372 };
1373
1374 template <typename Return, typename... Params, typename T, bool isNoexcept>
1375 struct signature_prepend_param_impl<Return(Params...)&&, T, isNoexcept>
1376 : public std::true_type
1377 {
1378 using type = Return(T, Params...) && noexcept(isNoexcept);
1379 };
1380
1381 template <typename Return, typename... Params, typename T, bool isNoexcept>
1382 struct signature_prepend_param_impl<Return(Params..., ...)&&, T, isNoexcept>
1383 : public std::true_type
1384 {
1385 using type = Return(T, Params..., ...) && noexcept(isNoexcept);
1386 };
1387
1388 template <typename Return, typename... Params, typename T, bool isNoexcept>
1389 struct signature_prepend_param_impl<Return(Params...) const, T, isNoexcept>
1390 : public std::true_type
1391 {
1392 using type = Return(T, Params...) const noexcept(isNoexcept);
1393 };
1394
1395 template <typename Return, typename... Params, typename T, bool isNoexcept>
1396 struct signature_prepend_param_impl<Return(Params..., ...) const, T, isNoexcept>
1397 : public std::true_type
1398 {
1399 using type = Return(T, Params..., ...) const noexcept(isNoexcept);
1400 };
1401
1402 template <typename Return, typename... Params, typename T, bool isNoexcept>
1403 struct signature_prepend_param_impl<Return(Params...) const&, T, isNoexcept>
1404 : public std::true_type
1405 {
1406 using type = Return(T, Params...) const& noexcept(isNoexcept);
1407 };
1408
1409 template <typename Return, typename... Params, typename T, bool isNoexcept>
1410 struct signature_prepend_param_impl<Return(Params..., ...) const&, T, isNoexcept>
1411 : public std::true_type
1412 {
1413 using type = Return(T, Params..., ...) const& noexcept(isNoexcept);
1414 };
1415
1416 template <typename Return, typename... Params, typename T, bool isNoexcept>
1417 struct signature_prepend_param_impl<Return(Params...) const&&, T, isNoexcept>
1418 : public std::true_type
1419 {
1420 using type = Return(T, Params...) const&& noexcept(isNoexcept);
1421 };
1422
1423 template <typename Return, typename... Params, typename T, bool isNoexcept>
1424 struct signature_prepend_param_impl<Return(Params..., ...) const&&, T, isNoexcept>
1425 : public std::true_type
1426 {
1427 using type = Return(T, Params..., ...) const&& noexcept(isNoexcept);
1428 };
1429
1430 // Todo: When msvc some day supports deducing noexcept, we can further simplify this.
1431 template <typename Signature, typename T, typename Trait = signature_remove_noexcept<Signature>>
1432 struct signature_prepend_param_
1433 : public signature_prepend_param_impl<typename Trait::type, T, Trait::value>
1434 {
1435 };
1436
1437 template <typename T>
1438 struct signature_prepend_param
1439 {
1440 template <typename Signature>
1441 using type = signature_prepend_param_<Signature, T>;
1442 };
1443 }
1444
1445 template <typename Signature, typename T>
1447 : public detail::signature_apply_trait<Signature, detail::signature_prepend_param<T>::template type>
1448 {
1449 };
1450
1454}
1455
1456namespace mimicpp::detail
1457{
1458 template <typename First, typename Second, bool reversed = false>
1459 struct is_overloadable_with
1460 : public std::conditional_t<
1461 reversed,
1462 std::false_type,
1463 is_overloadable_with<Second, First, true>>
1464 {
1465 };
1466
1467 template <typename First, typename Second>
1468 requires(
1469 !std::same_as<
1472 struct is_overloadable_with<First, Second, false>
1473 : public std::true_type
1474 {
1475 };
1476
1477 template <typename Return1, typename Return2, typename... Params, bool reversed>
1478 struct is_overloadable_with<Return1(Params...), Return2(Params...) const, reversed>
1479 : public std::true_type
1480 {
1481 };
1482
1483 template <typename Return1, typename Return2, typename... Params, bool reversed>
1484 struct is_overloadable_with<Return1(Params...)&, Return2(Params...) const&, reversed>
1485 : public std::true_type
1486 {
1487 };
1488
1489 template <typename Return1, typename Return2, typename... Params, bool reversed>
1490 struct is_overloadable_with<Return1(Params...)&, Return2(Params...)&&, reversed>
1491 : public std::true_type
1492 {
1493 };
1494
1495 template <typename Return1, typename Return2, typename... Params, bool reversed>
1496 struct is_overloadable_with<Return1(Params...)&, Return2(Params...) const&&, reversed>
1497 : public std::true_type
1498 {
1499 };
1500
1501 template <typename Return1, typename Return2, typename... Params, bool reversed>
1502 struct is_overloadable_with<Return1(Params...) const&, Return2(Params...)&&, reversed>
1503 : public std::true_type
1504 {
1505 };
1506
1507 template <typename Return1, typename Return2, typename... Params, bool reversed>
1508 struct is_overloadable_with<Return1(Params...) const&, Return2(Params...) const&&, reversed>
1509 : public std::true_type
1510 {
1511 };
1512
1513 template <typename Return1, typename Return2, typename... Params, bool reversed>
1514 struct is_overloadable_with<Return1(Params...)&&, Return2(Params...) const&&, reversed>
1515 : public std::true_type
1516 {
1517 };
1518
1519 template <typename Signature>
1520 using normalize_overload_t = signature_remove_noexcept_t<
1522}
1523
1524MIMICPP_DETAIL_MODULE_EXPORT namespace mimicpp
1525{
1533
1534 template <typename First, typename Second>
1536 : public detail::is_overloadable_with<
1537 detail::normalize_overload_t<First>,
1538 detail::normalize_overload_t<Second>>
1539 {
1540 };
1541
1545
1546 namespace detail
1547 {
1548 template <typename First, typename... Others>
1549 [[nodiscard]]
1550 consteval bool is_overload_set() noexcept
1551 {
1552 if constexpr (0 == sizeof...(Others))
1553 {
1554 return true;
1555 }
1556 else
1557 {
1558 return (... && is_overloadable_with<First, Others>::value)
1559 && is_overload_set<Others...>();
1560 }
1561 }
1562 }
1563
1571
1572 template <typename First, typename... Others>
1574 : public std::bool_constant<
1575 detail::is_overload_set<detail::normalize_overload_t<First>, detail::normalize_overload_t<Others>...>()>
1576 {
1577 };
1578
1582
1591
1595 template <>
1597 {
1598 using type = std::uint8_t;
1599 };
1600
1604 template <>
1606 {
1607 using type = std::uint16_t;
1608 };
1609
1613 template <>
1615 {
1616 using type = std::uint32_t;
1617 };
1618
1622 template <>
1624 {
1625 using type = std::uint64_t;
1626 };
1627
1631}
1632
1633#endif
#define MIMICPP_DETAIL_MODULE_EXPORT
Definition Config.hpp:19
Determines, whether the given signature has default call-convention.
Definition TypeTraits.hpp:195
constexpr TypeMatcher< T > type
Matcher, which can be used as a last resort to disambiguate similar overloads.
Definition GeneralMatchers.hpp:297
typename signature_call_convention< Signature >::type signature_call_convention_t
Convenience alias, exposing the type member alias of the actual type-trait.
Definition Fwd.hpp:102
typename signature_param_list< Signature >::type signature_param_list_t
Convenience alias, exposing the type member alias of the actual type-trait.
Definition Fwd.hpp:294
typename signature_remove_call_convention< Signature >::type signature_remove_call_convention_t
Convenience alias, exposing the type member alias of the actual type-trait.
Definition Fwd.hpp:118
typename signature_remove_noexcept< Signature >::type signature_remove_noexcept_t
Convenience alias, exposing the type member alias of the actual type-trait.
Definition Fwd.hpp:70
Definition Call.hpp:24
ValueCategory
Definition Fwd.hpp:34
@ lvalue
Definition Fwd.hpp:35
@ rvalue
Definition Fwd.hpp:36
detail::DefaultCallInterface< Derived, Signature > call_interface_t
Definition TypeTraits.hpp:257
std::type_identity_t< Signature > add_call_convention_t
Definition TypeTraits.hpp:254
detail::default_call_convention tag_t
Definition TypeTraits.hpp:248
std::type_identity_t< Signature > remove_call_convention_t
Definition TypeTraits.hpp:251
Primary template, purposely undefined.
Definition Fwd.hpp:355
Primary template.
Definition TypeTraits.hpp:1576
Primary template.
Definition TypeTraits.hpp:1539
Primary template, purposely undefined.
Definition TypeTraits.hpp:940
Primary template, purposely undefined.
Definition TypeTraits.hpp:1031
Primary template, purposely undefined.
Definition TypeTraits.hpp:602
Primary template, purposely undefined.
Definition TypeTraits.hpp:1122
detail::default_call_convention type
Definition TypeTraits.hpp:213
Primary template, purposely undefined.
Definition Fwd.hpp:94
Primary template.
Definition TypeTraits.hpp:1228
Primary template.
Definition TypeTraits.hpp:1139
typename detail::signature_remove_ref_qualifier_impl< typename detail::signature_remove_const_qualifier_impl< typename detail::signature_remove_noexcept< signature_remove_call_convention_t< Signature > >::type, false >::type, false >::type type
Definition TypeTraits.hpp:1140
Primary template.
Definition TypeTraits.hpp:620
util::type_list< Params... > type
Definition TypeTraits.hpp:1326
Primary template.
Definition TypeTraits.hpp:1320
Primary template.
Definition TypeTraits.hpp:1200
Primary template.
Definition TypeTraits.hpp:1448
Primary template.
Definition TypeTraits.hpp:1251
Primary template, purposely undefined.
Definition TypeTraits.hpp:274
typename call_convention_traits< signature_call_convention_t< Signature > >::template remove_call_convention_t< Signature > type
Definition TypeTraits.hpp:275
Primary template, purposely undefined.
Definition TypeTraits.hpp:856
Primary template, purposely undefined.
Definition TypeTraits.hpp:486
Primary template, purposely undefined.
Definition TypeTraits.hpp:738
Return type
Definition TypeTraits.hpp:1178
Return type
Definition TypeTraits.hpp:1172
Primary template.
Definition TypeTraits.hpp:1166
std::uint8_t type
Definition TypeTraits.hpp:1598
std::uint16_t type
Definition TypeTraits.hpp:1607
std::uint32_t type
Definition TypeTraits.hpp:1616
std::uint64_t type
Definition TypeTraits.hpp:1625
Primary template, purposely undefined.
Definition Fwd.hpp:363
A very basic type-list template.
Definition TypeList.hpp:29