"ScL Feature"
/
ScL Feature
0.0.1
C++20 composable proxy wrapper with pluggable executor strategy
Toggle main menu visibility
Loading...
Searching...
No Matches
operator.h
Go to the documentation of this file.
1
#pragma once
2
26
27
#include <
scl/feature/reflection/access.h
>
28
#include <
scl/feature/reflection/type.h
>
29
#include <
scl/feature/type_traits/executor.h
>
30
#include <
scl/feature/type_traits/has_qualified_method.h
>
31
#include <scl/feature/type_traits/wrapper.h>
32
#include <scl/feature/wrapper_cast.h>
33
#include <scl/utility/preprocessor/forward.h>
34
35
#include <type_traits>
36
#include <utility>
37
38
// clang-format off
39
60
#define SCL_REFLECT_OPERATOR_EXEC_HELPERS(name) \
61
template <typename ScLExec, typename... ScLArgs> \
62
static constexpr bool operator_##name##_scl_has_exec_override = \
63
requires { \
64
static_cast< \
65
decltype(::std::remove_cvref_t<ScLExec>::operator_##name( \
66
::std::declval<ScLExec>(), ::std::declval<ScLArgs>()...)) \
67
(*)(ScLExec, ScLArgs...) \
68
>(&::std::remove_cvref_t<ScLExec>::operator_##name); \
69
}; \
70
template <typename ScLExec, typename... ScLArgs> \
71
static constexpr bool operator_##name##_scl_exec_noexcept = \
72
[]() constexpr noexcept -> bool { \
73
if constexpr (operator_##name##_scl_has_exec_override<ScLExec, ScLArgs...>) \
74
return noexcept(::std::remove_cvref_t<ScLExec>::operator_##name( \
75
::std::declval<ScLExec>(), ::std::declval<ScLArgs>()...)); \
76
return false; \
77
}();
78
92
#define SCL_REFLECT_OPERATOR_CALLER(op, name) \
93
struct operator_##name##_scl_caller \
94
{ \
95
template <typename ScLParam, typename... ScLParams, \
96
typename ScLObj, typename... ScLArgs> \
97
static constexpr auto call(ScLObj && scl_obj, ScLArgs &&... scl_args) \
98
-> decltype(::std::forward<ScLObj>(scl_obj) \
99
.template operator op
/**/
<ScLParam, ScLParams...>( \
100
::scl::wrapper_cast(::std::forward<ScLArgs>(scl_args))...)) \
101
{ \
102
return ::std::forward<ScLObj>(scl_obj) \
103
.template operator op
/**/
<ScLParam, ScLParams...>( \
104
::scl::wrapper_cast(::std::forward<ScLArgs>(scl_args))...); \
105
} \
106
};
107
124
#define SCL_REFLECT_OPERATOR_QUALS(op, name) \
125
template <typename ScLVal, typename... ScLArgs> \
126
static constexpr bool operator_##name##_scl_quals = \
127
SCL_HAS_QUALIFIED_METHOD(SCL_FORWARD(operator op), ScLVal, ScLArgs...); \
128
template <typename ScLParam, typename... ScLParams> \
129
struct operator_##name##_scl_template_quals \
130
{ \
131
template <typename ScLVal, typename... ScLArgs> \
132
static constexpr bool value = \
133
SCL_HAS_QUALIFIED_METHOD( \
134
SCL_FORWARD(template operator op
/**/
<ScLParam, ScLParams...>), \
135
ScLVal, ScLArgs...); \
136
};
137
150
#define SCL_REFLECT_OPERATOR_EXECUTOR_OVERRIDE_BASE(op, name, cv_ref) \
151
template <typename ScLExec = s_c_l_executor_type cv_ref, typename... ScLArgs> \
152
constexpr decltype(auto) operator op(ScLArgs &&... scl_args) cv_ref \
153
noexcept(operator_##name##_scl_exec_noexcept<ScLExec, ScLArgs...>) \
154
requires \
155
(::std::is_same_v<ScLExec, s_c_l_executor_type cv_ref> \
156
&& operator_##name##_scl_has_exec_override<ScLExec, ScLArgs...>) \
157
{ \
158
return ::std::remove_cvref_t<ScLExec>::operator_##name( \
159
SCL_EXECUTOR_ACCESS(cv_ref), \
160
::std::forward<ScLArgs>(scl_args)...); \
161
}
162
173
#define SCL_REFLECT_OPERATOR_BASE(op, name, cv_ref) \
174
noexcept (noexcept(SCL_EXECUTE_OVERRIDED(SCL_FORWARD(operator op), cv_ref))) \
175
requires \
176
(!operator_##name##_scl_has_exec_override<s_c_l_executor_type cv_ref, \
177
ScLArgs...> && \
178
requires \
179
{ \
180
SCL_ACCESS_DECLVAL(cv_ref).operator op( \
181
::scl::wrapper_cast(::std::declval<ScLArgs>())...); \
182
} && operator_##name##_scl_quals<decltype(SCL_ACCESS_DECLVAL(cv_ref)), \
183
decltype(::scl::wrapper_cast(::std::declval<ScLArgs>()))...>) \
184
{ \
185
return SCL_EXECUTE_OVERRIDED(SCL_FORWARD(operator op), cv_ref); \
186
}
187
199
#define SCL_REFLECT_TEMPLATE_OPERATOR_BASE(name, caller, cv_ref) \
200
noexcept(noexcept(SCL_EXECUTE_TEMPLATE_OVERRIDED(caller, cv_ref))) \
201
requires \
202
requires \
203
{ \
204
caller::template call<ScLParam, ScLParams...>( \
205
SCL_ACCESS_DECLVAL(cv_ref), ::std::declval<ScLArgs>()...); \
206
} && operator_##name##_scl_template_quals<ScLParam, ScLParams...> \
207
::template value<decltype(SCL_ACCESS_DECLVAL(cv_ref)), \
208
decltype(::scl::wrapper_cast(::std::declval<ScLArgs>()))...> \
209
{ \
210
return SCL_EXECUTE_TEMPLATE_OVERRIDED(caller, cv_ref); \
211
}
212
222
#define SCL_REFLECT_OPERATOR_HELPER(op, name, caller, cv_ref) \
223
SCL_REFLECT_OPERATOR_EXECUTOR_OVERRIDE_BASE(SCL_FORWARD(op), name, cv_ref) \
224
template <typename... ScLArgs> \
225
constexpr decltype(auto) operator op(ScLArgs &&... scl_args) cv_ref \
226
SCL_REFLECT_OPERATOR_BASE(SCL_FORWARD(op), name, cv_ref) \
227
template <typename ScLParam, typename... ScLParams, typename... ScLArgs> \
228
constexpr decltype(auto) operator op(ScLArgs &&... scl_args) cv_ref \
229
SCL_REFLECT_TEMPLATE_OPERATOR_BASE(name, caller, cv_ref)
230
237
#define SCL_REFLECT_OPERATOR_IMPL(op, name) \
238
SCL_REFLECT_OPERATOR_QUALS(SCL_FORWARD(op), name) \
239
SCL_REFLECT_OPERATOR_CALLER(SCL_FORWARD(op), name) \
240
SCL_REFLECT_OPERATOR_EXEC_HELPERS(name) \
241
SCL_REFLECT_OPERATOR_HELPER(SCL_FORWARD(op), name, operator_##name##_scl_caller, &) \
242
SCL_REFLECT_OPERATOR_HELPER(SCL_FORWARD(op), name, operator_##name##_scl_caller, &&) \
243
SCL_REFLECT_OPERATOR_HELPER(SCL_FORWARD(op), name, operator_##name##_scl_caller, const &) \
244
SCL_REFLECT_OPERATOR_HELPER(SCL_FORWARD(op), name, operator_##name##_scl_caller, const &&) \
245
SCL_REFLECT_OPERATOR_HELPER(SCL_FORWARD(op), name, operator_##name##_scl_caller, volatile &) \
246
SCL_REFLECT_OPERATOR_HELPER(SCL_FORWARD(op), name, operator_##name##_scl_caller, volatile &&) \
247
SCL_REFLECT_OPERATOR_HELPER(SCL_FORWARD(op), name, operator_##name##_scl_caller, const volatile &) \
248
SCL_REFLECT_OPERATOR_HELPER(SCL_FORWARD(op), name, operator_##name##_scl_caller, const volatile &&)
249
262
#define SCL_REFLECT_PREFIX_UNARY_OPERATOR_BASE(op, name, cv_ref) \
263
template <typename ScLExec = s_c_l_executor_type cv_ref> \
264
constexpr decltype(auto) operator op() cv_ref \
265
noexcept(operator_##name##_scl_exec_noexcept<ScLExec>) \
266
requires \
267
(::std::is_same_v<ScLExec, s_c_l_executor_type cv_ref> \
268
&& (operator_##name##_scl_has_exec_override<ScLExec> \
269
|| operator_##name##_scl_quals<decltype(SCL_ACCESS_DECLVAL(cv_ref))>)) \
270
{ \
271
if constexpr (operator_##name##_scl_has_exec_override<ScLExec>) \
272
{ \
273
return ::std::remove_cvref_t<ScLExec>::operator_##name( \
274
SCL_EXECUTOR_ACCESS(cv_ref)); \
275
} \
276
else \
277
{ \
278
return ::std::remove_cvref_t<ScLExec>::execute(SCL_EXECUTOR_ACCESS(cv_ref), \
279
[](auto && scl_e) -> decltype(auto) { \
280
return ::std::remove_cvref_t<ScLExec>::access(::std::forward<decltype(scl_e)>(scl_e)) \
281
.operator op(); \
282
}, SCL_EXECUTOR_ACCESS(cv_ref)); \
283
} \
284
}
285
297
#define SCL_REFLECT_POSTFIX_UNARY_OPERATOR_BASE(op, name, cv_ref) \
298
template <typename ScLExec = s_c_l_executor_type cv_ref> \
299
constexpr decltype(auto) operator op(int) cv_ref \
300
noexcept(operator_##name##_scl_exec_noexcept<ScLExec>) \
301
requires \
302
(::std::is_same_v<ScLExec, s_c_l_executor_type cv_ref> \
303
&& (operator_##name##_scl_has_exec_override<ScLExec> \
304
|| operator_##name##_scl_quals<decltype(SCL_ACCESS_DECLVAL(cv_ref)), int>)) \
305
{ \
306
if constexpr (operator_##name##_scl_has_exec_override<ScLExec>) \
307
{ \
308
return ::std::remove_cvref_t<ScLExec>::operator_##name( \
309
SCL_EXECUTOR_ACCESS(cv_ref)); \
310
} \
311
else \
312
{ \
313
return ::std::remove_cvref_t<ScLExec>::execute(SCL_EXECUTOR_ACCESS(cv_ref), \
314
[](auto && scl_e) -> decltype(auto) { \
315
return ::std::remove_cvref_t<ScLExec>::access(::std::forward<decltype(scl_e)>(scl_e)) \
316
.operator op(int{}); \
317
}, SCL_EXECUTOR_ACCESS(cv_ref)); \
318
} \
319
}
320
359
#define SCL_REFLECT_PREFIX_UNARY_OPERATOR(op, name) \
360
SCL_REFLECT_OPERATOR_QUALS(SCL_FORWARD(op), name) \
361
SCL_REFLECT_OPERATOR_EXEC_HELPERS(name) \
362
SCL_REFLECT_PREFIX_UNARY_OPERATOR_BASE(SCL_FORWARD(op), name, &) \
363
SCL_REFLECT_PREFIX_UNARY_OPERATOR_BASE(SCL_FORWARD(op), name, &&) \
364
SCL_REFLECT_PREFIX_UNARY_OPERATOR_BASE(SCL_FORWARD(op), name, const &) \
365
SCL_REFLECT_PREFIX_UNARY_OPERATOR_BASE(SCL_FORWARD(op), name, const &&) \
366
SCL_REFLECT_PREFIX_UNARY_OPERATOR_BASE(SCL_FORWARD(op), name, volatile &) \
367
SCL_REFLECT_PREFIX_UNARY_OPERATOR_BASE(SCL_FORWARD(op), name, volatile &&) \
368
SCL_REFLECT_PREFIX_UNARY_OPERATOR_BASE(SCL_FORWARD(op), name, const volatile &) \
369
SCL_REFLECT_PREFIX_UNARY_OPERATOR_BASE(SCL_FORWARD(op), name, const volatile &&)
370
385
#define SCL_REFLECT_MEMBER_PREFIX_UNARY_OPERATOR(op, name) \
386
SCL_REFLECT_OPERATOR_QUALS(SCL_FORWARD(op), name) \
387
SCL_REFLECT_OPERATOR_EXEC_HELPERS(name) \
388
SCL_REFLECT_PREFIX_UNARY_OPERATOR_BASE(SCL_FORWARD(op), name, &) \
389
SCL_REFLECT_PREFIX_UNARY_OPERATOR_BASE(SCL_FORWARD(op), name, &&) \
390
SCL_REFLECT_PREFIX_UNARY_OPERATOR_BASE(SCL_FORWARD(op), name, const &) \
391
SCL_REFLECT_PREFIX_UNARY_OPERATOR_BASE(SCL_FORWARD(op), name, const &&) \
392
SCL_REFLECT_PREFIX_UNARY_OPERATOR_BASE(SCL_FORWARD(op), name, volatile &) \
393
SCL_REFLECT_PREFIX_UNARY_OPERATOR_BASE(SCL_FORWARD(op), name, volatile &&) \
394
SCL_REFLECT_PREFIX_UNARY_OPERATOR_BASE(SCL_FORWARD(op), name, const volatile &) \
395
SCL_REFLECT_PREFIX_UNARY_OPERATOR_BASE(SCL_FORWARD(op), name, const volatile &&)
396
418
#define SCL_REFLECT_POSTFIX_UNARY_OPERATOR(op, name) \
419
SCL_REFLECT_OPERATOR_QUALS(SCL_FORWARD(op), name) \
420
SCL_REFLECT_OPERATOR_EXEC_HELPERS(name) \
421
SCL_REFLECT_POSTFIX_UNARY_OPERATOR_BASE(SCL_FORWARD(op), name, &) \
422
SCL_REFLECT_POSTFIX_UNARY_OPERATOR_BASE(SCL_FORWARD(op), name, &&) \
423
SCL_REFLECT_POSTFIX_UNARY_OPERATOR_BASE(SCL_FORWARD(op), name, const &) \
424
SCL_REFLECT_POSTFIX_UNARY_OPERATOR_BASE(SCL_FORWARD(op), name, const &&) \
425
SCL_REFLECT_POSTFIX_UNARY_OPERATOR_BASE(SCL_FORWARD(op), name, volatile &) \
426
SCL_REFLECT_POSTFIX_UNARY_OPERATOR_BASE(SCL_FORWARD(op), name, volatile &&) \
427
SCL_REFLECT_POSTFIX_UNARY_OPERATOR_BASE(SCL_FORWARD(op), name, const volatile &) \
428
SCL_REFLECT_POSTFIX_UNARY_OPERATOR_BASE(SCL_FORWARD(op), name, const volatile &&)
429
443
#define SCL_REFLECT_MEMBER_POSTFIX_UNARY_OPERATOR(op, name) \
444
SCL_REFLECT_OPERATOR_QUALS(SCL_FORWARD(op), name) \
445
SCL_REFLECT_OPERATOR_EXEC_HELPERS(name) \
446
SCL_REFLECT_POSTFIX_UNARY_OPERATOR_BASE(SCL_FORWARD(op), name, &) \
447
SCL_REFLECT_POSTFIX_UNARY_OPERATOR_BASE(SCL_FORWARD(op), name, &&) \
448
SCL_REFLECT_POSTFIX_UNARY_OPERATOR_BASE(SCL_FORWARD(op), name, const &) \
449
SCL_REFLECT_POSTFIX_UNARY_OPERATOR_BASE(SCL_FORWARD(op), name, const &&) \
450
SCL_REFLECT_POSTFIX_UNARY_OPERATOR_BASE(SCL_FORWARD(op), name, volatile &) \
451
SCL_REFLECT_POSTFIX_UNARY_OPERATOR_BASE(SCL_FORWARD(op), name, volatile &&) \
452
SCL_REFLECT_POSTFIX_UNARY_OPERATOR_BASE(SCL_FORWARD(op), name, const volatile &) \
453
SCL_REFLECT_POSTFIX_UNARY_OPERATOR_BASE(SCL_FORWARD(op), name, const volatile &&)
454
526
#define SCL_REFLECT_BINARY_OPERATOR(op, name) \
527
SCL_REFLECT_COMBINED_OPERATOR_IMPL(SCL_FORWARD(op), name)
528
548
#define SCL_REFLECT_MEMBER_BINARY_OPERATOR(op, name) \
549
SCL_REFLECT_OPERATOR_IMPL(SCL_FORWARD(op), name)
550
567
#define SCL_REFLECT_OPERATOR_WITH_ARGUMENTS(op, name) \
568
SCL_REFLECT_OPERATOR_IMPL(SCL_FORWARD(op), name)
569
570
// ============================================================================
571
// Hidden-friend operator reflection macros
572
// ============================================================================
573
//
574
// These are the friend-function ("hidden friend") analogues of the member-
575
// operator macros above. The generated overloads are free functions defined
576
// with the `friend` keyword inside the enclosing class body, so they are:
577
//
578
// • only findable via Argument-Dependent Lookup (ADL), not via
579
// unqualified or qualified member lookup;
580
// • invisible to `w.operator op(...)` call syntax.
581
//
582
// The wrapper is passed as an explicit first parameter `scl_self` with the
583
// same cv-ref qualifier that would be applied to `*this` in the member
584
// counterpart. Access to the executor goes through
585
// `SCL_FRIEND_EXECUTOR_ACCESS` (defined in access.h) rather than through
586
// `*this`; the wrapped value is resolved via `Executor::value` inside the
587
// execute dispatch.
588
//
589
// The class-level helper constructs (QUALS, CALLER, EXEC_HELPERS) are
590
// identical to those generated by the member variants — do not invoke both
591
// the member and friend macro for the same `name` in the same class body,
592
// as that would produce duplicate static member definitions.
593
//
594
// Note: `operator[]` and `operator()` must be non-static member functions
595
// in C++20, so there is no `SCL_REFLECT_FRIEND_OPERATOR_WITH_ARGUMENTS`.
596
608
#define SCL_REFLECT_FRIEND_OPERATOR_EXECUTOR_OVERRIDE_BASE(op, name, cv_ref) \
609
template <typename ScLExec = s_c_l_executor_type cv_ref, typename... ScLArgs> \
610
friend constexpr decltype(auto) operator op( \
611
s_c_l_type cv_ref scl_self, ScLArgs &&... scl_args) \
612
noexcept(operator_##name##_scl_exec_noexcept<ScLExec, ScLArgs...>) \
613
requires \
614
(::std::is_same_v<ScLExec, s_c_l_executor_type cv_ref> \
615
&& operator_##name##_scl_has_exec_override<ScLExec, ScLArgs...>) \
616
{ \
617
return ::std::remove_cvref_t<ScLExec>::operator_##name( \
618
SCL_FRIEND_EXECUTOR_ACCESS(scl_self, cv_ref), \
619
::std::forward<ScLArgs>(scl_args)...); \
620
}
621
632
#define SCL_REFLECT_FRIEND_OPERATOR_BASE(op, name, cv_ref) \
633
noexcept(noexcept(SCL_FRIEND_EXECUTE_OVERRIDED_NX(SCL_FORWARD(operator op), cv_ref))) \
634
requires \
635
(!operator_##name##_scl_has_exec_override<s_c_l_executor_type cv_ref, ScLArgs...> && \
636
requires \
637
{ \
638
SCL_ACCESS_DECLVAL(cv_ref).operator op( \
639
::scl::wrapper_cast(::std::declval<ScLArgs>())...); \
640
} && operator_##name##_scl_quals<decltype(SCL_ACCESS_DECLVAL(cv_ref)), \
641
decltype(::scl::wrapper_cast(::std::declval<ScLArgs>()))...>) \
642
{ \
643
return SCL_FRIEND_EXECUTE_OVERRIDED(SCL_FORWARD(operator op), scl_self, cv_ref); \
644
}
645
656
#define SCL_REFLECT_FRIEND_TEMPLATE_OPERATOR_BASE(name, caller, cv_ref) \
657
noexcept(noexcept(SCL_FRIEND_EXECUTE_TEMPLATE_OVERRIDED_NX(caller, cv_ref))) \
658
requires \
659
requires \
660
{ \
661
caller::template call<ScLParam, ScLParams...>( \
662
SCL_ACCESS_DECLVAL(cv_ref), ::std::declval<ScLArgs>()...); \
663
} && operator_##name##_scl_template_quals<ScLParam, ScLParams...> \
664
::template value<decltype(SCL_ACCESS_DECLVAL(cv_ref)), \
665
decltype(::scl::wrapper_cast(::std::declval<ScLArgs>()))...> \
666
{ \
667
return SCL_FRIEND_EXECUTE_TEMPLATE_OVERRIDED(caller, scl_self, cv_ref); \
668
}
669
679
#define SCL_REFLECT_FRIEND_OPERATOR_HELPER(op, name, caller, cv_ref) \
680
SCL_REFLECT_FRIEND_OPERATOR_EXECUTOR_OVERRIDE_BASE(SCL_FORWARD(op), name, cv_ref) \
681
template <typename... ScLArgs> \
682
friend constexpr decltype(auto) operator op( \
683
s_c_l_type cv_ref scl_self, ScLArgs &&... scl_args) \
684
SCL_REFLECT_FRIEND_OPERATOR_BASE(SCL_FORWARD(op), name, cv_ref) \
685
template <typename ScLParam, typename... ScLParams, typename... ScLArgs> \
686
friend constexpr decltype(auto) operator op( \
687
s_c_l_type cv_ref scl_self, ScLArgs &&... scl_args) \
688
SCL_REFLECT_FRIEND_TEMPLATE_OPERATOR_BASE(name, caller, cv_ref)
689
696
#define SCL_REFLECT_FRIEND_OPERATOR_IMPL(op, name) \
697
SCL_REFLECT_OPERATOR_QUALS(SCL_FORWARD(op), name) \
698
SCL_REFLECT_OPERATOR_CALLER(SCL_FORWARD(op), name) \
699
SCL_REFLECT_OPERATOR_EXEC_HELPERS(name) \
700
SCL_REFLECT_FRIEND_OPERATOR_HELPER(SCL_FORWARD(op), name, operator_##name##_scl_caller, &) \
701
SCL_REFLECT_FRIEND_OPERATOR_HELPER(SCL_FORWARD(op), name, operator_##name##_scl_caller, &&) \
702
SCL_REFLECT_FRIEND_OPERATOR_HELPER(SCL_FORWARD(op), name, operator_##name##_scl_caller, const &) \
703
SCL_REFLECT_FRIEND_OPERATOR_HELPER(SCL_FORWARD(op), name, operator_##name##_scl_caller, const &&) \
704
SCL_REFLECT_FRIEND_OPERATOR_HELPER(SCL_FORWARD(op), name, operator_##name##_scl_caller, volatile &) \
705
SCL_REFLECT_FRIEND_OPERATOR_HELPER(SCL_FORWARD(op), name, operator_##name##_scl_caller, volatile &&) \
706
SCL_REFLECT_FRIEND_OPERATOR_HELPER(SCL_FORWARD(op), name, operator_##name##_scl_caller, const volatile &) \
707
SCL_REFLECT_FRIEND_OPERATOR_HELPER(SCL_FORWARD(op), name, operator_##name##_scl_caller, const volatile &&)
708
719
#define SCL_REFLECT_FRIEND_PREFIX_UNARY_OPERATOR_BASE(op, name, cv_ref) \
720
template <typename ScLExec = s_c_l_executor_type cv_ref> \
721
friend constexpr decltype(auto) operator op(s_c_l_type cv_ref scl_self) \
722
noexcept(operator_##name##_scl_exec_noexcept<ScLExec>) \
723
requires \
724
(::std::is_same_v<ScLExec, s_c_l_executor_type cv_ref> \
725
&& (operator_##name##_scl_has_exec_override<ScLExec> \
726
|| operator_##name##_scl_quals<decltype(SCL_ACCESS_DECLVAL(cv_ref))>)) \
727
{ \
728
if constexpr (operator_##name##_scl_has_exec_override<ScLExec>) \
729
{ \
730
return ::std::remove_cvref_t<ScLExec>::operator_##name( \
731
SCL_FRIEND_EXECUTOR_ACCESS(scl_self, cv_ref)); \
732
} \
733
else \
734
{ \
735
return ::std::remove_cvref_t<ScLExec>::execute( \
736
SCL_FRIEND_EXECUTOR_ACCESS(scl_self, cv_ref), \
737
[](auto && scl_e) -> decltype(auto) { \
738
return ::std::remove_cvref_t<ScLExec>::access(::std::forward<decltype(scl_e)>(scl_e)) \
739
.operator op(); \
740
}, SCL_FRIEND_EXECUTOR_ACCESS(scl_self, cv_ref)); \
741
} \
742
}
743
754
#define SCL_REFLECT_FRIEND_POSTFIX_UNARY_OPERATOR_BASE(op, name, cv_ref) \
755
template <typename ScLExec = s_c_l_executor_type cv_ref> \
756
friend constexpr decltype(auto) operator op(s_c_l_type cv_ref scl_self, int) \
757
noexcept(operator_##name##_scl_exec_noexcept<ScLExec>) \
758
requires \
759
(::std::is_same_v<ScLExec, s_c_l_executor_type cv_ref> \
760
&& (operator_##name##_scl_has_exec_override<ScLExec> \
761
|| operator_##name##_scl_quals<decltype(SCL_ACCESS_DECLVAL(cv_ref)), int>)) \
762
{ \
763
if constexpr (operator_##name##_scl_has_exec_override<ScLExec>) \
764
{ \
765
return ::std::remove_cvref_t<ScLExec>::operator_##name( \
766
SCL_FRIEND_EXECUTOR_ACCESS(scl_self, cv_ref)); \
767
} \
768
else \
769
{ \
770
return ::std::remove_cvref_t<ScLExec>::execute( \
771
SCL_FRIEND_EXECUTOR_ACCESS(scl_self, cv_ref), \
772
[](auto && scl_e) -> decltype(auto) { \
773
return ::std::remove_cvref_t<ScLExec>::access(::std::forward<decltype(scl_e)>(scl_e)) \
774
.operator op(int{}); \
775
}, SCL_FRIEND_EXECUTOR_ACCESS(scl_self, cv_ref)); \
776
} \
777
}
778
794
#define SCL_REFLECT_REVERSE_COMBINED_HELPERS(op, name) \
795
template <typename ScLLhs, typename ScLValue> \
796
static constexpr bool operator_##name##_scl_reverse_viable() noexcept \
797
{ \
798
return requires(ScLLhs && scl_l, ScLValue && scl_v) \
799
{ static_cast<ScLLhs &&>(scl_l) op static_cast<ScLValue &&>(scl_v); }; \
800
}
801
827
#define SCL_REFLECT_REVERSE_FRIEND_OPERATOR_BASE(op, name, cv_ref) \
828
template <typename ScLLhs> \
829
friend constexpr decltype(auto) operator op( \
830
ScLLhs && scl_lhs, s_c_l_type cv_ref scl_self) \
831
noexcept(noexcept(SCL_FRIEND_REVERSE_EXECUTE_NX(SCL_FORWARD(op), cv_ref))) \
832
requires \
833
(!::scl::feature::is_wrapper_v<::std::remove_cvref_t<ScLLhs>> \
834
&& !::std::is_same_v<::std::remove_cvref_t<ScLLhs>, \
835
::std::remove_cvref_t<s_c_l_type>> \
836
&& operator_##name##_scl_reverse_viable<ScLLhs, \
837
decltype(SCL_ACCESS_DECLVAL(cv_ref))>()) \
838
{ \
839
return SCL_FRIEND_REVERSE_EXECUTE(SCL_FORWARD(op), scl_self, scl_lhs, cv_ref); \
840
}
841
853
#define SCL_REFLECT_COMBINED_OPERATOR_IMPL(op, name) \
854
SCL_REFLECT_OPERATOR_IMPL(SCL_FORWARD(op), name) \
855
SCL_REFLECT_REVERSE_COMBINED_HELPERS(SCL_FORWARD(op), name) \
856
SCL_REFLECT_REVERSE_FRIEND_OPERATOR_BASE(SCL_FORWARD(op), name, &) \
857
SCL_REFLECT_REVERSE_FRIEND_OPERATOR_BASE(SCL_FORWARD(op), name, &&) \
858
SCL_REFLECT_REVERSE_FRIEND_OPERATOR_BASE(SCL_FORWARD(op), name, const &) \
859
SCL_REFLECT_REVERSE_FRIEND_OPERATOR_BASE(SCL_FORWARD(op), name, const &&) \
860
SCL_REFLECT_REVERSE_FRIEND_OPERATOR_BASE(SCL_FORWARD(op), name, volatile &) \
861
SCL_REFLECT_REVERSE_FRIEND_OPERATOR_BASE(SCL_FORWARD(op), name, volatile &&) \
862
SCL_REFLECT_REVERSE_FRIEND_OPERATOR_BASE(SCL_FORWARD(op), name, const volatile &) \
863
SCL_REFLECT_REVERSE_FRIEND_OPERATOR_BASE(SCL_FORWARD(op), name, const volatile &&)
864
897
#define SCL_REFLECT_FRIEND_BINARY_OPERATOR(op, name) \
898
SCL_REFLECT_FRIEND_OPERATOR_IMPL(SCL_FORWARD(op), name)
899
918
#define SCL_REFLECT_FRIEND_PREFIX_UNARY_OPERATOR(op, name) \
919
SCL_REFLECT_OPERATOR_QUALS(SCL_FORWARD(op), name) \
920
SCL_REFLECT_OPERATOR_EXEC_HELPERS(name) \
921
SCL_REFLECT_FRIEND_PREFIX_UNARY_OPERATOR_BASE(SCL_FORWARD(op), name, &) \
922
SCL_REFLECT_FRIEND_PREFIX_UNARY_OPERATOR_BASE(SCL_FORWARD(op), name, &&) \
923
SCL_REFLECT_FRIEND_PREFIX_UNARY_OPERATOR_BASE(SCL_FORWARD(op), name, const &) \
924
SCL_REFLECT_FRIEND_PREFIX_UNARY_OPERATOR_BASE(SCL_FORWARD(op), name, const &&) \
925
SCL_REFLECT_FRIEND_PREFIX_UNARY_OPERATOR_BASE(SCL_FORWARD(op), name, volatile &) \
926
SCL_REFLECT_FRIEND_PREFIX_UNARY_OPERATOR_BASE(SCL_FORWARD(op), name, volatile &&) \
927
SCL_REFLECT_FRIEND_PREFIX_UNARY_OPERATOR_BASE(SCL_FORWARD(op), name, const volatile &) \
928
SCL_REFLECT_FRIEND_PREFIX_UNARY_OPERATOR_BASE(SCL_FORWARD(op), name, const volatile &&)
929
948
#define SCL_REFLECT_FRIEND_POSTFIX_UNARY_OPERATOR(op, name) \
949
SCL_REFLECT_OPERATOR_QUALS(SCL_FORWARD(op), name) \
950
SCL_REFLECT_OPERATOR_EXEC_HELPERS(name) \
951
SCL_REFLECT_FRIEND_POSTFIX_UNARY_OPERATOR_BASE(SCL_FORWARD(op), name, &) \
952
SCL_REFLECT_FRIEND_POSTFIX_UNARY_OPERATOR_BASE(SCL_FORWARD(op), name, &&) \
953
SCL_REFLECT_FRIEND_POSTFIX_UNARY_OPERATOR_BASE(SCL_FORWARD(op), name, const &) \
954
SCL_REFLECT_FRIEND_POSTFIX_UNARY_OPERATOR_BASE(SCL_FORWARD(op), name, const &&) \
955
SCL_REFLECT_FRIEND_POSTFIX_UNARY_OPERATOR_BASE(SCL_FORWARD(op), name, volatile &) \
956
SCL_REFLECT_FRIEND_POSTFIX_UNARY_OPERATOR_BASE(SCL_FORWARD(op), name, volatile &&) \
957
SCL_REFLECT_FRIEND_POSTFIX_UNARY_OPERATOR_BASE(SCL_FORWARD(op), name, const volatile &) \
958
SCL_REFLECT_FRIEND_POSTFIX_UNARY_OPERATOR_BASE(SCL_FORWARD(op), name, const volatile &&)
959
960
// clang-format on
access.h
Internal accessor macros for executor and value access in reflected methods.
has_qualified_method.h
Compile-time predicate macro for cv-ref qualifier detection.
type.h
Macro for declaring the wrapper type used by reflection macros.
executor.h
Executor type traits: interface detection and noexcept helpers.
src
scl
feature
reflection
operator.h
Generated by
1.18.0