|
ScL Feature 0.0.1
C++20 composable proxy wrapper with pluggable executor strategy
|
Compile-time reflection for wrapper types. More...
Files | |
| file | src/scl/feature/reflection/access.h |
| Internal accessor macros for executor and value access in reflected methods. | |
| file | src/scl/feature/reflection/method.h |
| Compile-time method reflection macros for wrapper types. | |
| file | src/scl/feature/reflection/operator.h |
| Compile-time operator reflection macros for wrapper types. | |
| file | src/scl/feature/reflection/property.h |
| Compile-time property reflection macro for wrapper types. | |
| file | src/scl/feature/reflection/reflect.h |
| Primary template for the reflection mixin chain. | |
| file | src/scl/feature/reflection.h |
| ScL Feature compile-time method reflection utilities. | |
| file | src/scl/feature/reflection/type.h |
| Macro for declaring the wrapper type used by reflection macros. | |
Classes | |
| class | scl::feature::reflect< Wrapper, Executor, Type > |
| Primary (terminal) template for the reflection mixin chain. More... | |
| class | scl::feature::reflect_operators< Wrapper, Executor > |
| CRTP mixin that reflects all standard C++ operators through the executor. More... | |
Macros | |
| #define | SCL_REFLECT_BINARY_OPERATOR(op, name) |
Generates proxy binary operators that reflect op from the wrapped object through the executor, for all 8 cv-ref qualifier combinations. | |
| #define | SCL_REFLECT_FRIEND_BINARY_OPERATOR(op, name) |
Generates hidden-friend proxy binary operators that reflect op from the wrapped object through the executor, for all 8 cv-ref qualifier combinations. | |
| #define | SCL_REFLECT_FRIEND_POSTFIX_UNARY_OPERATOR(op, name) |
Generates hidden-friend proxy postfix-unary operators that reflect op from the wrapped object through the executor, for all 8 cv-ref qualifier combinations. | |
| #define | SCL_REFLECT_FRIEND_PREFIX_UNARY_OPERATOR(op, name) |
Generates hidden-friend proxy prefix-unary operators that reflect op from the wrapped object through the executor, for all 8 cv-ref qualifier combinations. | |
| #define | SCL_REFLECT_MEMBER_BINARY_OPERATOR(op, name) |
| Generates member-only proxy binary operators (no hidden-friend variants). | |
| #define | SCL_REFLECT_MEMBER_POSTFIX_UNARY_OPERATOR(op, name) |
| Generates member-only proxy postfix-unary operators (no hidden-friend variants). | |
| #define | SCL_REFLECT_MEMBER_PREFIX_UNARY_OPERATOR(op, name) |
| Generates member-only proxy prefix-unary operators (no hidden-friend variants). | |
| #define | SCL_REFLECT_METHOD(name) |
Generates proxy methods that reflect method from the wrapped object through the executor, for all 8 cv-ref qualifier combinations. | |
| #define | SCL_REFLECT_OPERATOR_WITH_ARGUMENTS(op, name) |
Generates proxy call/subscript operators that reflect op from the wrapped object through the executor, for all 8 cv-ref qualifier combinations. | |
| #define | SCL_REFLECT_POSTFIX_UNARY_OPERATOR(op, name) |
Generates proxy postfix-unary operators that reflect op from the wrapped object through the executor, for all 8 cv-ref qualifier combinations. | |
| #define | SCL_REFLECT_PREFIX_UNARY_OPERATOR(op, name) |
Generates proxy prefix-unary operators that reflect op from the wrapped object through the executor, for all 8 cv-ref qualifier combinations. | |
| #define | SCL_REFLECT_TYPE(type, executor) |
Declares the wrapper and executor types for use by SCL_REFLECT_METHOD. | |
Compile-time reflection for wrapper types.
Provides the macros and types needed to generate proxy members that transparently forward calls from a wrapper to the held object through an executor, preserving all cv-ref qualifiers.
| Symbol | Purpose |
|---|---|
SCL_REFLECT_TYPE(Wrapper, Executor) | Declares the type aliases required by SCL_REFLECT_METHOD and SCL_REFLECT_PROPERTY. Must appear first inside the wrapper class body. |
SCL_REFLECT_METHOD(method) | Generates 24 proxy overloads (3 × 8 cv-ref) that dispatch through the executor. |
SCL_REFLECT_PROPERTY(prop) | Generates a wrapper data member that proxies a single field through the executor, with optional executor override via property_<name>. |
scl::feature::reflect | CRTP mixin base class; specialisations inject reflected members. |
| #define SCL_REFLECT_BINARY_OPERATOR | ( | op, | |
| name ) |
Generates proxy binary operators that reflect op from the wrapped object through the executor, for all 8 cv-ref qualifier combinations.
For each of the 8 cv-ref qualifiers (&, &&, const&, const&&, volatile&, volatile&&, const volatile&, const volatile&&) three overloads are generated:
Executor::operator_##name existsoperator_##name(Executor cv_ref, args...) member whose first parameter matches the wrapper's cv-ref qualification exactly (detected via a function-pointer cast), the reflected operator calls that member directly, bypassing Executor::execute.noexcept is propagated from the override. When the execute path is taken, noexcept follows Executor::execute.is_wrapper_v), so w1 + w2 resolves unambiguously to the member overload. The reverse path has no executor-override shortcut — the operator_##name override convention applies to the wrapper-left (member) overloads only — but it still routes through Executor::execute, so cross-cutting behaviour applies on both sides.SCL_HAS_QUALIFIED_METHOD relies on return-type discrimination, overloads of the target operator with different cv-ref qualifiers must return different types.| op | The C++ binary operator token (e.g. +, -, ==). |
| name | Short unique name identifying the operator (plain identifier, e.g. op_add). |
| #define SCL_REFLECT_FRIEND_BINARY_OPERATOR | ( | op, | |
| name ) |
Generates hidden-friend proxy binary operators that reflect op from the wrapped object through the executor, for all 8 cv-ref qualifier combinations.
Identical in structure to SCL_REFLECT_BINARY_OPERATOR but generates friend free functions instead of member functions. Each generated overload takes the wrapper itself as its first (cv-ref-qualified) parameter and is only findable via Argument-Dependent Lookup (ADL).
SCL_REFLECT_BINARY_OPERATOR w.operator op(args) — NOT valid (no member function generated).w op args — valid via ADL.SCL_REFLECT_BINARY_OPERATOR: overloads with different cv-ref qualifiers must return distinct types so that SCL_HAS_QUALIFIED_METHOD can distinguish them.SCL_REFLECT_BINARY_OPERATOR for the same name name in the same class body produces duplicate static member definitions.| op | The C++ binary operator token (e.g. +, -, ==). |
| name | Short unique name identifying the operator (plain identifier, e.g. op_add). |
| #define SCL_REFLECT_FRIEND_POSTFIX_UNARY_OPERATOR | ( | op, | |
| name ) |
Generates hidden-friend proxy postfix-unary operators that reflect op from the wrapped object through the executor, for all 8 cv-ref qualifier combinations.
Identical in structure to SCL_REFLECT_POSTFIX_UNARY_OPERATOR but generates friend free functions. Each overload takes a dummy int parameter (standard C++ postfix-operator signature).
SCL_REFLECT_POSTFIX_UNARY_OPERATOR for the same name | op | The C++ postfix-unary operator token (++ or --). |
| name | Short unique name identifying the operator (plain identifier). |
| #define SCL_REFLECT_FRIEND_PREFIX_UNARY_OPERATOR | ( | op, | |
| name ) |
Generates hidden-friend proxy prefix-unary operators that reflect op from the wrapped object through the executor, for all 8 cv-ref qualifier combinations.
Identical in structure to SCL_REFLECT_PREFIX_UNARY_OPERATOR but generates friend free functions. The wrapper itself is passed as the cv-ref-qualified operand; the operator is only ADL-findable.
SCL_REFLECT_PREFIX_UNARY_OPERATOR for the same name | op | The C++ prefix-unary operator token (e.g. -, ++, *). |
| name | Short unique name identifying the operator (plain identifier). |
| #define SCL_REFLECT_MEMBER_BINARY_OPERATOR | ( | op, | |
| name ) |
Generates member-only proxy binary operators (no hidden-friend variants).
Use when the operator must be a non-static member function in C++20 (e.g. operator=, compound assignment operators). Generates the same 24 member overloads as the member subset of SCL_REFLECT_BINARY_OPERATOR without any friend counterparts.
operator=, operator*=, operator/=, operator%=, operator+=, operator-=, operator<<=, operator>>=, operator&=, operator|=, operator^=.| op | The C++ binary operator token. |
| name | Short unique name identifying the operator (plain identifier). |
| #define SCL_REFLECT_MEMBER_POSTFIX_UNARY_OPERATOR | ( | op, | |
| name ) |
Generates member-only proxy postfix-unary operators (no hidden-friend variants).
Use when the operator must be a non-static member function. Generates 8 member overloads (one per cv-ref qualifier) without the additional hidden-friend overloads that SCL_REFLECT_POSTFIX_UNARY_OPERATOR produces.
| op | The C++ postfix-unary operator token (++ or --). |
| name | Short unique name identifying the operator (plain identifier). |
| #define SCL_REFLECT_MEMBER_PREFIX_UNARY_OPERATOR | ( | op, | |
| name ) |
Generates member-only proxy prefix-unary operators (no hidden-friend variants).
Use when the operator must be a non-static member function in C++20 (e.g. operator->). Generates 8 member overloads (one per cv-ref qualifier) with the same dispatch logic as SCL_REFLECT_PREFIX_UNARY_OPERATOR, but without the additional hidden-friend overloads.
| op | The C++ prefix-unary operator token. |
| name | Short unique name identifying the operator (plain identifier). |
| #define SCL_REFLECT_METHOD | ( | name | ) |
Generates proxy methods that reflect method from the wrapped object through the executor, for all 8 cv-ref qualifier combinations.
For each of the 8 cv-ref qualifiers (&, &&, const&, const&&, volatile&, volatile&&, const volatile&, const volatile&&) three overloads are generated:
template<typename... ScLArgs>, active when Executor::method_##name existstemplate<typename... ScLArgs>, active when no executor override is foundtemplate<typename\ ScLParam,\ typename... ScLParams,\ typename... ScLArgs>This gives 24 overloads in total (3 × 8); the executor-override and execute-path overloads are mutually exclusive via their requires clauses, so at most 16 are active for any given executor.
method_##name(Executor cv_ref, args...) member whose first parameter matches the wrapper's cv-ref qualification exactly (detected via a function-pointer cast, the same technique as has_execute_v), the reflected method calls that member directly, bypassing Executor::execute. This lets the executor provide a custom implementation for specific methods.If no such member exists, the execute-path overload is activated instead.
Executor::execute(exec, callable, args...) so that executor strategies (e.g. locking, tracing) can intercept it. The callable receives the same args... and invokes the method on the wrapped value.The executor is obtained at runtime via scl::feature::executor_trait<WrapperType>::executor(self). There is no default implementation of executor_trait — every wrapper type must provide an explicit specialization.
The wrapped value is then obtained by calling Executor::access(executor_ref).
requires clause with two conditions:method must be callable with the given arguments (after scl::wrapper_cast) for the particular cv-ref qualification.SCL_HAS_QUALIFIED_METHOD must confirm that the wrapped object has a dedicated overload for that qualifier (not an implicit cv-widening fallback). This prevents, for example, a const& proxy from being generated when only a mutable & overload exists on the target.Explicit-template overloads use method_##name##_scl_template_quals for qualifier discrimination instead of method_##name##_scl_quals. The struct template forwards to SCL_HAS_QUALIFIED_METHOD with the token sequence template method<P,Ps...> (assembled via SCL_FORWARD) so it works even for purely-template methods where deduction without explicit arguments would fail — see SCL_REFLECT_TEMPLATE_METHOD_BASE for details.
SCL_HAS_QUALIFIED_METHOD relies on return-type discrimination, overloads of the target method with different cv-ref qualifiers must return different types. If two overloads return the same type, the macro will produce a false negative. method is a template on the wrapped object (e.g. template<typename\ T>\ T\ convert()), users can call the reflected method with explicit template arguments: wrapper.convert<double>().Internally this is handled by two helper constructs generated inside the enclosing class by SCL_REFLECT_METHOD_CALLER and SCL_REFLECT_METHOD_QUALS:
method_##name##_scl_caller — a struct whose static call<P,Ps...>(obj, args...) wraps the .template method<P,Ps...>(args...) call. The object parameter (ScLObj) is dependent, so the template keyword appears only in a dependent context and name lookup is deferred to instantiation. Without this indirection, .template foo<...> on a non-dependent type would be a hard parse error (not SFINAE) when foo is not a template.method_##name##_scl_quals — a variable template that computes the qualifier-discrimination predicate for the deduced-args overload.method_##name##_scl_template_quals — a struct template parameterised over <P,Ps...> with an inner value<V,As...> variable template. Delegates to SCL_HAS_QUALIFIED_METHOD with the token sequence template method<P,Ps...> so that the predicate evaluates the method call with concrete template arguments, handling purely-template methods that do not have any deduction-friendly non-template overload.When method is not a template, the call function fails to instantiate (SFINAE via trailing return type), the requires clause evaluates to false, and the explicit-template-args overload is silently discarded.
| method | Unqualified method name (plain identifier). |
| #define SCL_REFLECT_OPERATOR_WITH_ARGUMENTS | ( | op, | |
| name ) |
Generates proxy call/subscript operators that reflect op from the wrapped object through the executor, for all 8 cv-ref qualifier combinations.
Identical in structure to SCL_REFLECT_BINARY_OPERATOR. Intended for operators whose syntax requires the argument list to be enclosed in brackets — specifically operator[] and operator() — but works for any operator accepted by SCL_REFLECT_OPERATOR_IMPL.
| op | The C++ operator token ([] or ()). |
| name | Short unique name identifying the operator (plain identifier, e.g. op_call). |
| #define SCL_REFLECT_POSTFIX_UNARY_OPERATOR | ( | op, | |
| name ) |
Generates proxy postfix-unary operators that reflect op from the wrapped object through the executor, for all 8 cv-ref qualifier combinations.
Identical in structure to SCL_REFLECT_PREFIX_UNARY_OPERATOR but generates overloads that take a dummy int parameter (standard C++ postfix signature: operator op(int)).
Only member-function overloads are generated. Use SCL_REFLECT_FRIEND_POSTFIX_UNARY_OPERATOR explicitly if an ADL-only (member-less) postfix operator is required.
| op | The C++ postfix-unary operator token (++ or --). |
| name | Short unique name identifying the operator (plain identifier, e.g. op_postinc). |
| #define SCL_REFLECT_PREFIX_UNARY_OPERATOR | ( | op, | |
| name ) |
Generates proxy prefix-unary operators that reflect op from the wrapped object through the executor, for all 8 cv-ref qualifier combinations.
For each of the 8 cv-ref qualifiers a single overload is generated that uses if constexpr to dispatch to either the executor override or the execute path (unlike binary operators which generate two separate constrained overloads).
Only member-function overloads are generated. Unary operators have a single operand, so there is no reverse-operand case for a hidden friend to cover; use SCL_REFLECT_FRIEND_PREFIX_UNARY_OPERATOR explicitly if an ADL-only (member-less) unary operator is required.
operator_##name(Executor cv_ref) override, orop overload for the given qualifier (checked via SCL_HAS_QUALIFIED_METHOD).operator_##name(Executor cv_ref) member (detected via a function-pointer cast), the generated operator calls that member directly, bypassing Executor::execute.noexcept is propagated from the override. When the execute path is taken, noexcept follows Executor::execute.| op | The C++ prefix-unary operator token (e.g. -, ++, *). |
| name | Short unique name identifying the operator (plain identifier, e.g. op_neg). |
| #define SCL_REFLECT_TYPE | ( | type, | |
| executor ) |
Declares the wrapper and executor types for use by SCL_REFLECT_METHOD.
Must appear inside the class body before any SCL_REFLECT_METHOD invocations.
A specialization of scl::feature::executor_trait must also be provided for type.
| type | The unqualified wrapper class name. |
| executor | The unqualified executor type name. |