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);
|
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 {
|
inline const std::string& Node::Scalar() const {
|
||||||
if (!m_isValid)
|
if (!m_isValid)
|
||||||
throw InvalidNode(m_invalidKey);
|
throw InvalidNode(m_invalidKey);
|
||||||
|
|||||||
@ -66,6 +66,9 @@ class YAML_CPP_API Node {
|
|||||||
T as() const;
|
T as() const;
|
||||||
template <typename T, typename S>
|
template <typename T, typename S>
|
||||||
T as(const S& fallback) const;
|
T as(const S& fallback) const;
|
||||||
|
template <typename T>
|
||||||
|
bool into(T& target) const;
|
||||||
|
|
||||||
const std::string& Scalar() const;
|
const std::string& Scalar() const;
|
||||||
|
|
||||||
const std::string& Tag() const;
|
const std::string& Tag() const;
|
||||||
|
|||||||
@ -645,6 +645,28 @@ TEST(NodeTest, AccessNonexistentKeyOnConstNode) {
|
|||||||
ASSERT_FALSE(other["5"]);
|
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 {
|
class NodeEmitterTest : public ::testing::Test {
|
||||||
protected:
|
protected:
|
||||||
void ExpectOutput(const std::string& output, const Node& node) {
|
void ExpectOutput(const std::string& output, const Node& node) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user