-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathany.hpp
83 lines (66 loc) · 2.41 KB
/
any.hpp
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
#pragma once
#include <typeinfo>
#include <nall/traits.hpp>
namespace nall {
struct any {
any() = default;
any(const any& source) { operator=(source); }
any(any&& source) { operator=(move(source)); }
template<typename T> any(const T& value) { operator=(value); }
~any() { reset(); }
explicit operator bool() const { return container; }
auto reset() -> void { if(container) { delete container; container = nullptr; } }
auto type() const -> const std::type_info& {
return container ? container->type() : typeid(void);
}
template<typename T> auto is() const -> bool {
return type() == typeid(typename remove_reference<T>::type);
}
template<typename T> auto get() -> T& {
if(!is<T>()) throw;
return static_cast<holder<typename remove_reference<T>::type>*>(container)->value;
}
template<typename T> auto get() const -> const T& {
if(!is<T>()) throw;
return static_cast<holder<typename remove_reference<T>::type>*>(container)->value;
}
template<typename T> auto get(const T& fallback) const -> const T& {
if(!is<T>()) return fallback;
return static_cast<holder<typename remove_reference<T>::type>*>(container)->value;
}
template<typename T> auto operator=(const T& value) -> any& {
using auto_t = typename conditional<is_array<T>::value, typename remove_extent<typename add_const<T>::type>::type*, T>::type;
if(type() == typeid(auto_t)) {
static_cast<holder<auto_t>*>(container)->value = (auto_t)value;
} else {
if(container) delete container;
container = new holder<auto_t>((auto_t)value);
}
return *this;
}
auto operator=(const any& source) -> any& {
if(container) { delete container; container = nullptr; }
if(source.container) container = source.container->copy();
return *this;
}
auto operator=(any&& source) -> any& {
if(container) delete container;
container = source.container;
source.container = nullptr;
return *this;
}
private:
struct placeholder {
virtual ~placeholder() = default;
virtual auto type() const -> const std::type_info& = 0;
virtual auto copy() const -> placeholder* = 0;
};
placeholder* container = nullptr;
template<typename T> struct holder : placeholder {
holder(const T& value) : value(value) {}
auto type() const -> const std::type_info& { return typeid(T); }
auto copy() const -> placeholder* { return new holder(value); }
T value;
};
};
}