Merge 3be2e1b28f into 39f737443b
This commit is contained in:
commit
38f81b1193
@ -199,3 +199,79 @@ YAML::Node node = YAML::Load("start: [1, 3, 0]");
|
|||||||
Vec3 v = node["start"].as<Vec3>();
|
Vec3 v = node["start"].as<Vec3>();
|
||||||
node["end"] = Vec3(2, -1, 0);
|
node["end"] = Vec3(2, -1, 0);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Partial specialization
|
||||||
|
|
||||||
|
If you need to specialize the `convert` struct for a set of types instead of just one you can use partial specialization with the help of `std::enable_if` (SFINAE).
|
||||||
|
|
||||||
|
Here is a small example showing how to partially specialize the `convert` struct for all types deriving from a base class:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Base class
|
||||||
|
class A
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
A() = default;
|
||||||
|
A(int a) : a{a} {}
|
||||||
|
|
||||||
|
// virtual load/emit methods
|
||||||
|
virtual void load(const YAML::Node &node) {
|
||||||
|
a = node["a"].as<int>();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual YAML::Node emit() const {
|
||||||
|
YAML::Node node;
|
||||||
|
node["a"] = a;
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
int a;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Derived class
|
||||||
|
class B : public A
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
B() = default;
|
||||||
|
B(int a, int b) : A{a}, b{b} {}
|
||||||
|
|
||||||
|
// override virtual load/emit methods
|
||||||
|
virtual void load(const YAML::Node &node) override {
|
||||||
|
A::load(node);
|
||||||
|
b = node["b"].as<int>();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual YAML::Node emit() const override {
|
||||||
|
YAML::Node node = A::emit();
|
||||||
|
node["b"] = b;
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
int b;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Implementation of convert::{encode,decode} for all classes derived from or being A
|
||||||
|
namespace YAML {
|
||||||
|
template<typename T>
|
||||||
|
struct convert<T, typename std::enable_if<std::is_base_of<A, T>::value>::type> {
|
||||||
|
static Node encode(const T &rhs) {
|
||||||
|
Node node = rhs.emit();
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool decode(const Node &node, T &rhs) {
|
||||||
|
rhs.load(node);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Which can then be use like this:
|
||||||
|
```cpp
|
||||||
|
YAML::Node node = YAML::Load("{a: 1, b: 2}");
|
||||||
|
B b = node.as<B>();
|
||||||
|
b.a = 12;
|
||||||
|
b.b = 42;
|
||||||
|
node = b;
|
||||||
|
```
|
||||||
@ -34,7 +34,7 @@
|
|||||||
namespace YAML {
|
namespace YAML {
|
||||||
class Binary;
|
class Binary;
|
||||||
struct _Null;
|
struct _Null;
|
||||||
template <typename T>
|
template <typename T, typename Enable>
|
||||||
struct convert;
|
struct convert;
|
||||||
} // namespace YAML
|
} // namespace YAML
|
||||||
|
|
||||||
|
|||||||
@ -141,7 +141,7 @@ YAML_CPP_API bool operator==(const Node& lhs, const Node& rhs);
|
|||||||
|
|
||||||
YAML_CPP_API Node Clone(const Node& node);
|
YAML_CPP_API Node Clone(const Node& node);
|
||||||
|
|
||||||
template <typename T>
|
template <typename T, typename Enable = void>
|
||||||
struct convert;
|
struct convert;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
92
test/integration/convert_partial_specialization_test.cpp
Normal file
92
test/integration/convert_partial_specialization_test.cpp
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
#include "yaml-cpp/emitterstyle.h"
|
||||||
|
#include "yaml-cpp/eventhandler.h"
|
||||||
|
#include "yaml-cpp/yaml.h" // IWYU pragma: keep
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
|
// Base class
|
||||||
|
class A {
|
||||||
|
public:
|
||||||
|
A() = default;
|
||||||
|
A(int a) : a{a} {}
|
||||||
|
|
||||||
|
// virtual load/emit methods
|
||||||
|
virtual void load(const YAML::Node &node) { a = node["a"].as<int>(); }
|
||||||
|
|
||||||
|
virtual YAML::Node emit() const {
|
||||||
|
YAML::Node node;
|
||||||
|
node["a"] = a;
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
int a{};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Derived class
|
||||||
|
class B : public A {
|
||||||
|
public:
|
||||||
|
B() = default;
|
||||||
|
B(int a, int b) : A{a}, b{b} {}
|
||||||
|
|
||||||
|
// override virtual load/emit methods
|
||||||
|
virtual void load(const YAML::Node &node) override {
|
||||||
|
A::load(node);
|
||||||
|
b = node["b"].as<int>();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual YAML::Node emit() const override {
|
||||||
|
YAML::Node node = A::emit();
|
||||||
|
node["b"] = b;
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
int b{};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Implementation of convert::{encode,decode} for all classes derived from or
|
||||||
|
// being A
|
||||||
|
namespace YAML {
|
||||||
|
template <typename T>
|
||||||
|
struct convert<T, typename std::enable_if<std::is_base_of<A, T>::value>::type> {
|
||||||
|
static Node encode(const T &rhs) {
|
||||||
|
Node node = rhs.emit();
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool decode(const Node &node, T &rhs) {
|
||||||
|
rhs.load(node);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
TEST(ConvertPartialSpecializationTest, EncodeBaseClass) {
|
||||||
|
Node n(Load("{a: 1}"));
|
||||||
|
A a = n.as<A>();
|
||||||
|
EXPECT_EQ(a.a, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ConvertPartialSpecializationTest, EncodeDerivedClass) {
|
||||||
|
Node n(Load("{a: 1, b: 2}"));
|
||||||
|
B b = n.as<B>();
|
||||||
|
EXPECT_EQ(b.a, 1);
|
||||||
|
EXPECT_EQ(b.b, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ConvertPartialSpecializationTest, DecodeBaseClass) {
|
||||||
|
A a(1);
|
||||||
|
Node n;
|
||||||
|
n = a;
|
||||||
|
EXPECT_EQ(a.a, n["a"].as<int>());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ConvertPartialSpecializationTest, DecodeDerivedClass) {
|
||||||
|
B b(1, 2);
|
||||||
|
Node n;
|
||||||
|
n = b;
|
||||||
|
EXPECT_EQ(b.a, n["a"].as<int>());
|
||||||
|
EXPECT_EQ(b.b, n["b"].as<int>());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
} // namespace YAML
|
||||||
Loading…
Reference in New Issue
Block a user