C++20 header-only library. Part of the ScL Toolkit.
ScL.Feature provides scl::wrapper<Value, Executors...> — a composable proxy wrapper that
delegates method calls to the held value through a chain of executor templates. Each executor
can transparently add cross-cutting behaviour such as copy-on-write semantics, thread safety,
or deferred invocation without modifying the wrapped type. Licensed under The Unlicense.
- Wrapper —
scl::wrapper<Value, Executors...>, a composable proxy:- Delegates all method calls to the held
Valuethrough a left-folded executor chain - Adjacent duplicate executors in the list are collapsed automatically
- Defaults to
feature::inplace::plainwhen no executor is specified
- Delegates all method calls to the held
- Executors (
scl::feature::inplace):inplace::plain— storesValuein-place with zero overhead; serves as the default executorinplace::uninitialized— holdsValuein correctly sized and aligned raw storage, enabling deferred (lazy) construction
- Wrapper guard —
scl::feature::wrapper_guard<Refer>:- RAII guard that calls
guard()/unguard()on the executor at construction / destruction - Works uniformly for wrapper references and plain value references
- Exposes
value()preserving the cv- and ref-qualifiers of the incoming reference
- RAII guard that calls
- Type traits (
scl::feature):is_wrapper_v<T>— checks whetherTis awrapperspecialization (strips cv-qualifiers)is_compatible_with_v<Expected, Test>—Testis the same as or derived fromExpected; for wrapper specialisations with the same executor the check is applied recursively to value typesis_compatible_with_part_of_v<Expected, Test>—Expected(a wrapper) recursively contains a value compatible withTestis_part_compatible_with_v<Expected, Test>—Test(a wrapper) recursively contains a value compatible withExpected
- Concepts (
scl::feature::concepts):concepts::wrapper<T>— satisfied whenTis awrapperspecializationconcepts::compatible_with<Expected, T>concepts::compatible_with_part_of<Expected, T>concepts::part_compatible_with<Expected, T>
- Reflection macros (
scl/feature/reflection/):SCL_REFLECT_TYPE(Type, Member)— declares the wrapper identity alias required by method reflectionSCL_REFLECT_METHOD(method)— generates 16 proxy overloads (8 cv-ref qualifications × 2: deduced and explicit template arguments); each overload is constrained so only overloads that actually exist on the wrapped type are exposed
- C++20 compiler (MSVC 19.30+, GCC 13+, Clang 16+)
- CMake 3.20+
- scl::utility (fetched automatically via CMake)
Add the module as a subdirectory and link against the interface target:
add_subdirectory(module/feature)
target_link_libraries(your_target PRIVATE scl::feature)#include <scl/feature/reflection/method.h>
#include <scl/feature/inplace/plain.h>
struct Target {
short get() &;
int get() const &;
float get() &&;
};
struct MyWrapper {
Executor<Target> m_executor; // any executor
SCL_REFLECT_TYPE(MyWrapper, m_executor);
SCL_REFLECT_METHOD(get) // generates 16 overloads, 3 survive constraints
};
MyWrapper w{42};
w.get(); // Target::get() & → short
std::as_const(w).get() // Target::get() const & → int
std::move(w).get(); // Target::get() && → float