blob: 86bbfea2e748a7ea9fe95cedea58bd7425e3fa47 (
plain)
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
91
92
93
94
95
96
97
98
|
#ifndef value_hh_INCLUDED
#define value_hh_INCLUDED
#include <memory>
#include <unordered_map>
#include "units.hh"
namespace Kakoune
{
struct bad_value_cast {};
struct Value
{
Value() = default;
template<typename T>
Value(T&& val) : m_value{new Model<T>{std::forward<T>(val)}} {}
Value(const Value& val) = delete;
Value(Value&&) = default;
Value& operator=(const Value& val) = delete;
Value& operator=(Value&& val) = default;
explicit operator bool() const { return (bool)m_value; }
template<typename T>
bool is_a() const
{
return m_value and m_value->type() == typeid(T);
}
template<typename T>
T& as()
{
if (not is_a<T>())
throw bad_value_cast{};
return static_cast<Model<T>*>(m_value.get())->m_content;
}
template<typename T>
const T& as() const
{
return const_cast<Value*>(this)->as<T>();
}
private:
struct Concept
{
virtual ~Concept() {}
virtual const std::type_info& type() const = 0;
};
template<typename T>
struct Model : public Concept
{
Model(T&& val) : m_content(std::move(val)) {}
const std::type_info& type() const override { return typeid(T); }
T m_content;
};
std::unique_ptr<Concept> m_value;
};
struct ValueId : public StronglyTypedNumber<ValueId, int>
{
constexpr ValueId(int value = 0) : StronglyTypedNumber(value) {}
static ValueId get_free_id()
{
static ValueId next;
return next++;
}
};
using ValueMap = std::unordered_map<ValueId, Value>;
}
namespace std
{
template<>
struct hash<Kakoune::ValueId>
{
size_t operator()(Kakoune::ValueId val) const
{
return std::hash<int>()((int)val);
}
};
}
#endif // value_hh_INCLUDED
|