Extending support for class types as constant template parameters with reflection.
One way to think about the library is that it is a generalization of existing language and library features by way of extension:
| C++26 | With ctp |
|---|---|
std::meta::reflect_constant(v) |
ctp::reflect_constant(v) |
std::meta::reflect_constant_array(r) |
ctp::reflect_constant_array(v) |
std::define_static_object(v) |
ctp::define_static_object(v) |
template <auto V> |
template <ctp::Param V> |
template <T V> |
template <ctp::Param<T> V> |
It's really as simple as that. If you wanted a std::string template parameter, you cannot write this:
template <std::string S> // ill-formed
struct C {
// would use S here
};But you can now write this:
template <ctp::Param<std::string> S>
struct C {
// use S.value or S.get() here
};The library supports: std::string_view and std::string, std::optional<T> and std::variant<Ts...>, std::tuple<Ts...>, std::reference_wrapper<T>, and std::vector<T>.
If you want to add support for your own (non-C++20 structural) type, you can do so by specializing ctp::Reflect<T>, which has to have three public members:
-
A type named
target_type. This is you are going to deserialize as, which can be just the very sameT. But ifTrequires allocation, then it cannot be, and you'll have to come up with an approximation (e.g. forstd::string, thetarget_typeisstd::string_view). -
The function
static consteval auto serialize(Serializer&, T const&) -> void;, which pushes an arbitrary amount of reflections onto theSerializer. These reflections define template-argument-equivalence forT: two values that serialize the same reflections will produce the same object. -
A deserialization function, which is going to take as its input each reflection that was serialized by
serialize, in one of three forms. Choose the one most appropriate for your type:// 1. Take each serialization as a constant template parameter template <meta::info R1, meta::info R2, ...> static consteval auto deserialize() -> target_type; // 2. Take each serialization as a function parameter static consteval auto deserialize(meta:info R1, meta::info R2, ...) -> target_type; // 3. Take the splice of serialization as a function parameter static consteval auto deserialize_constants(T1 t1, T2 t2, ...) -> target_type;
In the library,
variantuses the first form,vectorandstringuse the second, andoptional,tuple,reference_wrapper,span, andstring_viewuse the third.