Skip to content

Commit 5d7de05

Browse files
Allowing partial specialization of the convert struct
This is done by adding a second, defaulted, template parameter that can be used in conjunction of std::enable_if An example of usage is added to the tutorial
1 parent 51ce663 commit 5d7de05

File tree

3 files changed

+72
-2
lines changed

3 files changed

+72
-2
lines changed

docs/Tutorial.md

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,4 +198,74 @@ Then you could use `Vec3` wherever you could use any other type:
198198
YAML::Node node = YAML::Load("start: [1, 3, 0]");
199199
Vec3 v = node["start"].as<Vec3>();
200200
node["end"] = Vec3(2, -1, 0);
201+
```
202+
203+
## Partial specialization
204+
205+
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).
206+
207+
Here is a small example showing how to partially specialize the `convert` struct for all types deriving from a base class:
208+
209+
```cpp
210+
// Base class
211+
class A
212+
{
213+
public:
214+
// virtual load/emit methods
215+
virtual void load(const YAML::Node &node) {
216+
a = node["a"].as<int>();
217+
}
218+
219+
virtual YAML::Node emit() const {
220+
YAML::Node node;
221+
node["a"] = a;
222+
return node;
223+
}
224+
225+
int a;
226+
};
227+
228+
// Derived class
229+
class B : public A
230+
{
231+
public:
232+
// override virtual load/emit methods
233+
virtual void load(const YAML::Node &node) override {
234+
A::load(node);
235+
b = node["b"].as<int>();
236+
}
237+
238+
virtual YAML::Node emit() const override {
239+
YAML::Node node = A::emit();
240+
node["b"] = b;
241+
return node;
242+
}
243+
244+
int b;
245+
};
246+
247+
// Implementation of convert::{encode,decode} for all classes derived from or being A
248+
namespace YAML {
249+
template<typename T>
250+
struct convert<T, typename std::enable_if<std::is_base_of<A, T>::value>::type> {
251+
static Node encode(const T &rhs) {
252+
Node node = rhs.emit();
253+
return node;
254+
}
255+
256+
static bool decode(const Node &node, T &rhs) {
257+
rhs.load(node);
258+
return true;
259+
}
260+
};
261+
}
262+
```
263+
264+
Which can then be use like this:
265+
```cpp
266+
YAML::Node node = YAML::Load("{a: 1, b: 2}");
267+
B b = node.as<B>();
268+
b.a = 12;
269+
b.b = 42;
270+
node = b;
201271
```

include/yaml-cpp/node/convert.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
namespace YAML {
2828
class Binary;
2929
struct _Null;
30-
template <typename T>
30+
template <typename T, typename Enable>
3131
struct convert;
3232
} // namespace YAML
3333

include/yaml-cpp/node/node.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ YAML_CPP_API bool operator==(const Node& lhs, const Node& rhs);
141141

142142
YAML_CPP_API Node Clone(const Node& node);
143143

144-
template <typename T>
144+
template <typename T, typename Enable = void>
145145
struct convert;
146146
}
147147

0 commit comments

Comments
 (0)