-
Notifications
You must be signed in to change notification settings - Fork 294
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat formats: automatic serialization/deserialization based on Boost.PFR #469
feat formats: automatic serialization/deserialization based on Boost.PFR #469
Conversation
return this->contents[index]; | ||
}; | ||
|
||
constexpr operator char&() const { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wut
}; | ||
constexpr ConstexprString(std::array<char, Size> data) noexcept : contents(data) {}; | ||
template <std::size_t OtherSize> | ||
constexpr ConstexprString<Size + OtherSize> operator+(const ConstexprString<OtherSize>& other) const noexcept { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems like operator+
is not really needed for now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It can be used, for example, to generate constexpr SQL queries via Boost.PFR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, I'll give it a second thought later
template <std::size_t Size = 1> | ||
struct ConstexprString { | ||
static constexpr auto kSize = Size; | ||
std::array<char, Size> contents; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
<array>
brings in <algorithm>
in typical stdlib implementations, and that's a very heavy header. We try to minimize the usage of <array>
in public headers
@@ -14,7 +14,7 @@ namespace formats::parse { | |||
namespace impl { | |||
|
|||
template <typename T, typename Value> | |||
inline bool Is(Value&& value) { | |||
constexpr inline bool Is(Value&& value) { | |||
if constexpr(std::is_convertible_v<T, std::int64_t>) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
double
and bool
are convertible to int64_t
0784a5f
to
a81e72c
Compare
} // namespace impl | ||
|
||
template <typename T, typename... Params> | ||
class SerializationConfig { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[big] After some internal discussion: we want to reduce the amount of template metaprogramming and make SerializationConfig
value-based. Details of struct fields serialization and so on will be stored inside SerializationConfig
itself, not inside its template parameters.
SerializationConfig
should contain a tuple of FieldConfig
for each field. FieldConfig
should be parametrized with the parsed type. The config creation will look like this:
.With<"field">({.max_items = 10, .items = {.min = 42}})
With
takes a single parameter of type FieldConfig<(type of "field")>
, which is a struct
with all optional
members, like std::optional<std::size_t> max_items
and FieldConfig<(type of items)> items
. This config is assigned to the SerializationConfig
's tuple element corresponding to "field"
.
FieldConfig
should be able to be specialized for the parsed type. For example, FieldConfig
will be specialized for array-like ranges to include min_items
, max_items
and items
fields, and for numeric types to include min
and max
fields of appropriate type.
FieldConfig
for structs should contain a single reference to the struct's SerializationConfig
, which should be default-initialized with formats::universal::kSerialization<T>
. The "reference" part is important, as it allows to create recursive structs.
Add a test that contains a simple recursive type:
struct Node {
int value;
std::vector<Node> children;
};
Test universal serialization on it.
That's the gist of the vision for value-based serialization config. Feel free to ask questions here or in PM.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Functions will still be able to use if constexpr
and alike by passing around const FieldConfig<T>&
in template parameters. Remember that all those SerializationConfig
and FieldConfig
are stored inside variable templates, so it's possible to use addresses of those variables and their contents in templates, even in C++17
Continuing in #472 |
Example