1#pragma once
2
3#include <typeinfo>
4#include <type_traits>
5#include <stdexcept>
6namespace mbgl {
7namespace util {
8
9class bad_any_cast : public std::bad_cast {
10public:
11 const char* what() const noexcept override {
12 return "bad any_cast<>()";
13 }
14};
15/**
16 * A variant of `std::any` for non-copyable types.
17 *
18 * Use `unique_any` for non-copyable types (e.g. `std::unique_ptr<T>`)
19 * or to ensure that no copies are made of copyable types that are
20 * moved in.
21 *
22 * `uniqe_any` differs from `std::any` in that it does not support copy construction
23 * or copy assignment. It also does not require the contained type to be copy
24 * constructible.
25 *
26 * The `any_cast<T>()` methods work similar to `std::any_cast<T>()` except that
27 * non-copyable types may only be cast to references.
28 *
29 * Example usage:
30 * unique_any u1(3);
31 * auto u2 = unique_any(std::move(u1)); // u1 is moved from
32 * int i = any_cast<int>(u2);
33 *
34 * unique_any u2;
35 * u2 = std::unique_ptr<int>(new int);
36 * std::unique_ptr<int> iPtr = any_cast<std::unique_ptr<int>>(std::move(u2));
37 *
38 * Inspired by linb::any (https://github.com/thelink2012/any) and the
39 * libc++ implementation (https://github.com/llvm-mirror/libcxx).
40 */
41class unique_any final
42{
43public:
44 unique_any() = default;
45
46 //Copy constructor (deleted)
47 unique_any(const unique_any& rhs) = delete;
48
49 unique_any(unique_any&& rhs) : vtable(rhs.vtable) {
50 if (vtable) {
51 vtable->move(src: std::move(rhs.storage), dest&: storage);
52 }
53 rhs.vtable = nullptr;
54 }
55
56 // Constructs with a direct-initilizated object of type ValueType
57 template <typename ValueType,
58 typename _Vt = std::decay_t<ValueType>,
59 typename = std::enable_if_t<!std::is_same<_Vt, unique_any>::value> >
60 unique_any(ValueType&& value) {
61 create(std::forward<ValueType>(value));
62 }
63
64 ~unique_any() {
65 reset();
66 }
67
68 unique_any& operator=(unique_any&& rhs) {
69 unique_any(std::move(rhs)).swap(rhs&: *this);
70 return *this;
71 }
72
73 template <class ValueType,
74 typename = std::enable_if_t<!std::is_same<std::decay_t<ValueType>, unique_any>::value> >
75 unique_any& operator=(ValueType&& rhs) {
76 unique_any(std::forward<ValueType>(rhs)).swap(rhs&: *this);
77 return *this;
78 }
79
80 void reset() {
81 if (vtable) {
82 vtable->destroy(storage);
83 vtable = nullptr;
84 }
85 }
86
87 void swap(unique_any& rhs) {
88 if (this == &rhs) {
89 return;
90 } else {
91 unique_any tmp(std::move(rhs));
92 rhs.vtable = vtable;
93 if (rhs.vtable) {
94 rhs.vtable->move(src: std::move(storage), dest&: rhs.storage);
95 }
96 vtable = tmp.vtable;
97 if (vtable) {
98 vtable->move(src: std::move(tmp.storage), dest&: storage);
99 }
100 }
101 }
102
103 const std::type_info& type() const {
104 return !has_value()? typeid(void) : vtable->type();
105 }
106
107 bool has_value() const {
108 return vtable != nullptr;
109 }
110
111private:
112
113 union Storage {
114 using StackStorage = std::aligned_storage_t<3*sizeof(void*), std::alignment_of<void*>::value>;
115 Storage() = default;
116
117 void * dynamic { nullptr };
118 StackStorage stack;
119 };
120
121 template<typename T>
122 struct AllocateOnStack : std::integral_constant<bool,
123 sizeof(T) <= sizeof(Storage::stack)
124 && std::alignment_of<T>::value <= std::alignment_of<Storage::StackStorage>::value
125 && std::is_nothrow_move_constructible<T>::value> {
126 };
127
128 struct VTable {
129 virtual ~VTable() = default;
130 virtual void move(Storage&& src, Storage& dest) = 0;
131 virtual void destroy(Storage&) = 0;
132 virtual const std::type_info& type() = 0;
133 };
134
135 template <typename ValueType>
136 struct VTableHeap : public VTable {
137 void move(Storage&& src, Storage& dest) override {
138 dest.dynamic = src.dynamic;
139 src.dynamic = nullptr;
140 }
141
142 void destroy(Storage& s) override {
143 delete reinterpret_cast<ValueType*>(s.dynamic);
144 }
145
146 const std::type_info& type() override {
147 return typeid(ValueType);
148 }
149 };
150
151 template <typename ValueType>
152 struct VTableStack : public VTable {
153 void move(Storage&& src, Storage& dest) override {
154 new (&dest.stack) ValueType(std::move(reinterpret_cast<ValueType&>(src.stack)));
155 destroy(s&: src);
156 }
157
158 void destroy(Storage& s) override {
159 reinterpret_cast<ValueType&>(s.stack).~ValueType();
160 }
161
162 const std::type_info& type() override {
163 return typeid(ValueType);
164 }
165 };
166
167 template <typename ValueType>
168 static VTable* vtableForType() {
169 using VTableType = std::conditional_t<AllocateOnStack<ValueType>::value, VTableStack<ValueType>, VTableHeap<ValueType> >;
170 static VTableType vtable;
171 return &vtable;
172 }
173
174 template <typename ValueType, typename _Vt>
175 std::enable_if_t<AllocateOnStack<_Vt>::value>
176 createStorage(ValueType&& value) {
177 new (&storage.stack) _Vt(std::forward<ValueType>(value));
178 }
179
180 template <typename ValueType, typename _Vt>
181 std::enable_if_t<!AllocateOnStack<_Vt>::value>
182 createStorage(ValueType&& value) {
183 storage.dynamic = new _Vt(std::forward<ValueType>(value));
184 }
185
186 template <typename ValueType>
187 void create(ValueType&& value) {
188 using _Vt = std::decay_t<ValueType>;
189 vtable = vtableForType<_Vt>();
190 createStorage<ValueType, _Vt>(std::forward<ValueType>(value));
191 }
192
193 VTable* vtable { nullptr };
194 Storage storage;
195
196protected:
197 template<class ValueType>
198 friend const ValueType* any_cast(const unique_any* operand) ;
199
200 template<class ValueType>
201 friend ValueType* any_cast(unique_any* operand) ;
202
203 template<typename ValueType, typename _Vt = std::decay_t<ValueType> >
204 ValueType* cast()
205 {
206 return reinterpret_cast<ValueType *>(
207 AllocateOnStack<_Vt>::value ? &storage.stack : storage.dynamic);
208 }
209};
210
211template<typename ValueType>
212inline const ValueType* any_cast(const unique_any* any)
213{
214 return any_cast<ValueType>(const_cast<unique_any *>(any));
215}
216
217template<typename ValueType>
218inline ValueType* any_cast(unique_any* any)
219{
220 if(any == nullptr || any->type() != typeid(ValueType))
221 return nullptr;
222 else
223 return any->cast<ValueType>();
224}
225
226template<typename ValueType, typename _Vt = std::decay_t<ValueType> >
227inline ValueType any_cast(const unique_any& any)
228{
229 static_assert(std::is_constructible<ValueType, const _Vt&>::value,
230 "any_cast type can't construct copy of contained object");
231 auto temp = any_cast<_Vt>(&any);
232 if (temp == nullptr) {
233 throw bad_any_cast();
234 }
235 return static_cast<ValueType>(*temp);
236}
237
238template<typename ValueType, typename _Vt = std::decay_t<ValueType> >
239inline ValueType any_cast(unique_any& any)
240{
241 static_assert(std::is_constructible<ValueType, const _Vt&>::value,
242 "any_cast type can't construct copy of contained object");
243 auto temp = any_cast<_Vt>(&any);
244 if (temp == nullptr) {
245 throw bad_any_cast();
246 }
247 return static_cast<ValueType>(*temp);
248}
249
250template<typename ValueType, typename _Vt = std::remove_cv_t<ValueType> >
251inline ValueType any_cast(unique_any&& any)
252{
253 auto temp = any_cast<_Vt>(&any);
254 if (temp == nullptr) {
255 throw bad_any_cast();
256 }
257 auto retValue = static_cast<ValueType>(std::move(*temp));
258 any.reset();
259 return std::move(retValue);
260}
261
262} // namespace util
263} // namespace mbgl
264
265namespace std {
266
267inline void swap(mbgl::util::unique_any& lhs, mbgl::util::unique_any& rhs) {
268 lhs.swap(rhs);
269}
270
271} // namespace std
272

source code of qtlocation/src/3rdparty/mapbox-gl-native/include/mbgl/util/unique_any.hpp