-
Notifications
You must be signed in to change notification settings - Fork 2k
Open
Description
YAML is often used for configuration input, and it's a bit difficult to manage defaults:
Current:
inline bool validField(const YAML::Node& node, const std::string& field) noexcept {
if (node.IsDefined() && node[field].IsDefined() && !node[field].IsNull()) {
return true;
}
return false;
}
// The convert struct is helpful only once: for reading the defaults
// default = node.as<Cfg>();
Cfg readConfig(const YAML::Node& node, const Cfg& default) {
Cfg config = default;
if (validField(node, "first")) { config.first = node["first"].as<decltype(config.first)>();
// ...
// repeat for N number of fields
return config;
}
Proposed:
Cfg readConfig(const YAML::Node& node, Cfg default) {
// Note the change from const reference to value for default
node.into<Cfg>(default); // 100% usage of convert struct
return default;
}
Roadmap:
- Add templated update function to
Node
. Bikeshedding on name is on the table.into
just reads nice - Update the
as_if
struct with a function, sayupdate
, innode/impl.h
to not create the default variable - The
into
(newly added templated function) calls theupdate
function.
Proposed change in as_if
:
template <typename T, typename S>
struct as_if {
explicit as_if(const Node& node_) : node(node_) {}
const Node& node;
// current, can be replaced with the newer function
T operator()(const S& fallback) const {
if (!node.m_pNode)
return fallback;
T t;
if (convert<T>::decode(node, t))
return t;
return fallback;
}
// new
bool update(S& incoming) {
if (!node.m_pNode)
return false;
if (convert<T>::decode(node, incoming))
return true;
return false;
}
// compilers are smart enough to reorder `T t` after the inlining of `node.m_pNode` check
T operator()(const S& fallback) const {
T t;
if (update(t))
return t;
return fallback;
}
};
I can create a PR if needed, but I'm confused about the overloads for S = void
case
Metadata
Metadata
Assignees
Labels
No labels