Add an into() operator on Node to do optional assignment.
This adds an `into()` operator to the Node class modeled off the `get_to()` operator in the popular nlohmann::json library. (See: https://github.com/nlohmann/json#basic-usage) This operator assigns a casted value to an existing variable if that node has a defined value, and otherwise leaves the variable unchanged. It returns `true` if the variable was overwritten and `false` if the variable was unchanged. This operator is extremely useful in applications where YAML is being used as a configuration source that overrides default values coming from another source, e.g.: ```c++ struct MyConfig { int foo = 4; double bar = 5.0; std::string baz = "six"; }; MyConfig config; node["foo"].into(config.foo); node["bar"].into(config.bar); if (!node["baz"].into(config.baz)) std::cerr << "Using default value for .baz!" << std::endl; ```
This commit is contained in:
parent
5057a53293
commit
ff9a466152
@ -163,6 +163,14 @@ inline T Node::as(const S& fallback) const {
|
||||
return as_if<T, S>(*this)(fallback);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool Node::into(T& target) const {
|
||||
if (!this->IsDefined())
|
||||
return false;
|
||||
target = this->as<T>();
|
||||
return true;
|
||||
}
|
||||
|
||||
inline const std::string& Node::Scalar() const {
|
||||
if (!m_isValid)
|
||||
throw InvalidNode(m_invalidKey);
|
||||
|
||||
@ -66,6 +66,9 @@ class YAML_CPP_API Node {
|
||||
T as() const;
|
||||
template <typename T, typename S>
|
||||
T as(const S& fallback) const;
|
||||
template <typename T>
|
||||
bool into(T& target) const;
|
||||
|
||||
const std::string& Scalar() const;
|
||||
|
||||
const std::string& Tag() const;
|
||||
|
||||
@ -645,6 +645,28 @@ TEST(NodeTest, AccessNonexistentKeyOnConstNode) {
|
||||
ASSERT_FALSE(other["5"]);
|
||||
}
|
||||
|
||||
TEST(NodeTest, IntoExists) {
|
||||
Node node;
|
||||
node["A"] = 4;
|
||||
|
||||
int dest = 5;
|
||||
bool res = node["A"].into(dest);
|
||||
|
||||
ASSERT_TRUE(res);
|
||||
EXPECT_EQ(dest, 4);
|
||||
}
|
||||
|
||||
TEST(NodeTest, IntoMissing) {
|
||||
Node node;
|
||||
node["A"] = 4;
|
||||
|
||||
int dest = 5;
|
||||
bool res = node["B"].into(dest);
|
||||
|
||||
ASSERT_FALSE(res);
|
||||
EXPECT_EQ(dest, 5);
|
||||
}
|
||||
|
||||
class NodeEmitterTest : public ::testing::Test {
|
||||
protected:
|
||||
void ExpectOutput(const std::string& output, const Node& node) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user