From 8eef18882e06682f12d9830bfed0c9fe97dc6d65 Mon Sep 17 00:00:00 2001 From: Omer Ozarslan Date: Thu, 15 Jul 2021 09:41:08 -0500 Subject: [PATCH] Allow decoding types without a default constructor `YAML::decode_dispatcher::dispatch` is used for decoding `YAML::Node` to a type T when compiled with C++17 or newer. This is a backward compatible change as the default library implementation calls `YAML::convert::decode`. An example: ```cpp struct Vec3 { double x, y, z; Vec3(double x, double y, double z) : x(x), y(y), z(z) {} // ... }; namespace YAML { template<> struct decode_dispatcher { static std::optional dispatch(const Node& node) { if(!node.IsSequence() || node.size() != 3) return std::nullopt; return Vec3( node[0].as(), node[1].as(), node[2].as() ); } }; } ``` --- include/yaml-cpp/node/impl.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/include/yaml-cpp/node/impl.h b/include/yaml-cpp/node/impl.h index 312281f..e415275 100644 --- a/include/yaml-cpp/node/impl.h +++ b/include/yaml-cpp/node/impl.h @@ -15,6 +15,11 @@ #include #include +#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) +#include +#define YAML_CPP_HAS_DECODE_DISPATCHER +#endif + namespace YAML { inline Node::Node() : m_isValid(true), m_invalidKey{}, m_pMemory(nullptr), m_pNode(nullptr) {} @@ -88,6 +93,18 @@ inline NodeType::value Node::Type() const { // access // template helpers +#ifdef YAML_CPP_HAS_DECODE_DISPATCHER +template +struct decode_dispatcher { + static std::optional dispatch(const Node& node) { + T t; + if (convert::decode(node, t)) + return {t}; + return std::nullopt; + } +}; +#endif + template struct as_if { explicit as_if(const Node& node_) : node(node_) {} @@ -97,10 +114,14 @@ struct as_if { if (!node.m_pNode) return fallback; +#ifdef YAML_CPP_HAS_DECODE_DISPATCHER + return decode_dispatcher::dispatch(node).value_or(fallback); +#else T t; if (convert::decode(node, t)) return t; return fallback; +#endif } }; @@ -127,9 +148,15 @@ struct as_if { if (!node.m_pNode) throw TypedBadConversion(node.Mark()); +#ifdef YAML_CPP_HAS_DECODE_DISPATCHER + auto t = decode_dispatcher::dispatch(node); + if (t) + return *t; +#else T t; if (convert::decode(node, t)) return t; +#endif throw TypedBadConversion(node.Mark()); } };