feat: Allow decoding for types without default constructor - #1479
feat: Allow decoding for types without default constructor#1479SGSSGene wants to merge 1 commit into
Conversation
2897332 to
41be05a
Compare
9522ee9 to
d1f8ebc
Compare
|
Maybe it also enough to consider it as a fix for #506 |
alex-thiessen-for-siemens
left a comment
There was a problem hiding this comment.
I really don't like that interface, could we have something like template<> struct convert<std::expected<Vec3>> static auto decode(const Node& node) -> std::expected<Vec3> instead?
| ``` | ||
|
|
||
| ## Non-default constructible types (requires c++17 and newer) | ||
| Yaml-cpp also supports types that are not default constructible. For this one need to specialize `YAML::convert<std::optional<>>`. |
There was a problem hiding this comment.
default constructible -> default-constructible
| ``` | ||
|
|
||
| ## Non-default constructible types (requires c++17 and newer) | ||
| Yaml-cpp also supports types that are not default constructible. For this one need to specialize `YAML::convert<std::optional<>>`. |
There was a problem hiding this comment.
For this one need to specialize -> For this, one needs to specialize
| }; | ||
| ``` | ||
|
|
||
| you could write (for encoding the previous `convert<Vec3>` with the `encode` method is required) |
There was a problem hiding this comment.
for encoding the previous -> for encoding, the previous
| namespace YAML { | ||
| template<> | ||
| struct convert<std::optional<Vec3>> { | ||
| static bool decode(const Node& node, std::optional<Vec3>& rhs) { |
There was a problem hiding this comment.
this interface now has two bools (one return value, one std::optional-embedded), what's their combinatory semantics?
| // Implementation of convert::{encode,decode} for all classes derived from or being A | ||
| namespace YAML { | ||
| template<typename T> | ||
| template<typename T> |
There was a problem hiding this comment.
is it possible to clean all whitespace in a separate effort, adding a static check for that?
| // if available and supported include required header | ||
| // otherwise remove YAML_CPP_USE_OPTIONAL definition | ||
| #ifdef YAML_CPP_USE_OPTIONAL | ||
| #if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) |
There was a problem hiding this comment.
That's a weird check, maybe C++20 should be the base line so that more straightforward feature-test macros could be used instead.
| node["end"] = Vec3(2, -1, 0); | ||
| ``` | ||
|
|
||
| ## Non-default constructible types (requires c++17 and newer) |
There was a problem hiding this comment.
c++17 and newer -> C++17 or newer
| ```cpp | ||
| namespace YAML { | ||
| template<> | ||
| struct convert<std::optional<Vec3>> { |
There was a problem hiding this comment.
I'd doubt that std::optional is a great choice here, std::expected seems to be more appropriate, as it enables users to provide informative failure data more easily than e.g. via exception handling. It's been available in mainstream toolchains for 3-4 years now.
|
@alex-thiessen-for-siemens I think there is still plenty of room for discussion about this (or the other PRs). Currently yaml-cpp is based on c++11. I feel weird to add features that only work with newer c++ versions. Which is also why I am not sure if it really matters if we use With a similar argument I used Opinions from anyone are very welcome. Especially from people who would have concrete use cases and can easier imagine the pro/cons of the different APIs. |
If we switch to |
|
Sounds like a policy decision could be handy regarding how to proceed with adding functionality which would benefit or require recent C++ versions' features, like What this PR brings is added convenience and performance of not having to dynamically allocate non-default-constructible objects, right? That would count as optimization which can be offered exclusively to users of recent C++ versions, IMHO. This would avoid the awkward double-bool situation here. Those who stick to old yet battle-tested toolchain versions don't usually crave for most convenient library features, I'd suggest. |
This PR is inspired by #1010, but instead of creating a new customization point via
decode_dispatcherit reusesconvertby usingconvert<std::optional<T>>specialization for non-default constructible classes.If cmake variable
YAML_CPP_USE_OPTIONALis set (automatically set if target is c++17 or above) this new feature is activated. It can be deactivated by settingYAML_CPP_USE_OPTIONALto false to force old behavior if desired.When decoding a type
T, it will useconvert<std::optional<T>>and forward toconvert<T>if not available.The signature requirements are as before but by using the additional
std::optionalit allows us to delay the construction of our type T.Assume we have some type without default constructor:
you could write
To implement encoding for Vec3 one must still implement
convert<Vec3>with theencodemethod.Notes:
fixes #973 #993
alternative for PR #1010 and #1087
PR #1087 breaks API and relies on exception paths which I don't like, since this seems like normal control flow to me.