-
Notifications
You must be signed in to change notification settings - Fork 0
/
traverse-variant.h
90 lines (71 loc) · 2.73 KB
/
traverse-variant.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
// Copyright 2015 Red Blob Games <[email protected]>
// https://github.com/redblobgames/cpp-traverse
// License: Apache v2.0 <http://www.apache.org/licenses/LICENSE-2.0.html>
/**
* Plug-in to make mapbox::variant work with the traverse library.
*
* The traverse library is "multimethod" style so it can be extended with
* both new nouns (data types to be visited) and verbs (visit operations).
* This file only defines variant + cout and variant + binary serialization,
* but does not define variant + json or variant + lua.
*/
#ifndef TRAVERSE_VARIANT_H
#define TRAVERSE_VARIANT_H
#include "traverse.h"
#include "mapbox/variant.hpp"
#include "mapbox/variant_io.hpp"
namespace traverse {
// Using mapbox's variant here but if you use boost or another variant,
// change the includes above and these typedefs:
template<typename ...T> using variant = mapbox::util::variant<T...>;
using mapbox::util::apply_visitor;
struct CoutVariantVisitor {
CoutWriter& writer;
template<typename T> void operator()(const T& value) {
visit(writer, value);
}
};
template<typename ...Variants>
void visit(CoutWriter& writer, const variant<Variants...>& value) {
apply_visitor(CoutVariantVisitor{writer}, value);
}
struct BinarySerializeVariantHelper {
BinarySerialize& writer;
template<typename T> void operator()(const T& value) {
visit(writer, value);
}
};
template<typename ...Variants>
void visit(BinarySerialize& writer, const variant<Variants...>& value) {
unsigned which = value.which();
visit(writer, which);
apply_visitor(BinarySerializeVariantHelper{writer}, value);
}
template<typename VariantType>
void deserialize_variant_helper(BinaryDeserialize& reader,
unsigned which, unsigned index,
VariantType&) {
reader.errors << "Error: tried to deserialize variant " << which
<< " but there were only " << index << " types."
<< std::endl;
}
template<typename VariantType, typename First, typename ...Rest>
void deserialize_variant_helper(BinaryDeserialize& reader,
unsigned which, unsigned index,
VariantType& value) {
if (which == index) {
value.template set<First>();
visit(reader, value.template get<First>());
} else {
deserialize_variant_helper<VariantType, Rest...>(reader, which, index+1, value);
}
}
template<typename ...Variants>
void visit(BinaryDeserialize& reader, variant<Variants...>& value) {
unsigned which;
visit(reader, which);
deserialize_variant_helper<variant<Variants...>, Variants...>
(reader, which, 0, value);
}
}
#endif