Skip to content

Better support for "default" #973

@kunaltyagi

Description

@kunaltyagi

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, say update, in node/impl.h to not create the default variable
  • The into (newly added templated function) calls the update 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

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions