Medial Code Documentation
Loading...
Searching...
No Matches
any.h
Go to the documentation of this file.
1
6#ifndef DMLC_ANY_H_
7#define DMLC_ANY_H_
8
9// This code need c++11 to compile
10#include <typeinfo>
11#include <type_traits>
12#include <utility>
13#include <algorithm>
14#include <cstring>
15
16#include "./base.h"
17#include "./logging.h"
18
19namespace dmlc {
20// forward declare any;
21class any;
22
33template<typename T>
34inline T& get(any& src); // NOLINT(*)
35
46template<typename T>
47inline const T& get(const any& src);
48
59template<typename T>
60inline const T& unsafe_get(const any& src);
61
72template<typename T>
73inline T& unsafe_get(any& src); // NOLINT(*)
74
90class any {
91 public:
93 inline any() = default;
98 inline any(any&& other); // NOLINT(*)
103 inline any(const any& other); // NOLINT(*)
109 template<typename T>
110 inline any(T&& other); // NOLINT(*)
112 inline ~any();
118 inline any& operator=(any&& other);
124 inline any& operator=(const any& other);
131 template<typename T>
132 inline any& operator=(T&& other);
136 inline bool empty() const;
140 inline void clear();
145 inline void swap(any& other); // NOLINT(*)
149 inline const std::type_info& type() const;
151 template<typename T, typename... Args>
152 inline void construct(Args&&... args);
153
154 private:
156 // declare of helper class
157 template<typename T>
158 class TypeOnHeap;
159 template<typename T>
160 class TypeOnStack;
161 template<typename T>
162 class TypeInfo;
163 // size of stack space, it takes 32 bytes for one any type.
164 static const size_t kStack = sizeof(void*) * 3;
165 static const size_t kAlign = sizeof(void*);
166 // container use dynamic storage only when space runs lager
167 union Data {
168 // stack space
169 std::aligned_storage<kStack, kAlign>::type stack;
170 // pointer to heap space
171 void* pheap;
172 };
173 // type specific information
174 struct Type {
175 // destructor function
176 void (*destroy)(Data* data);
177 // copy constructor
178 void (*create_from_data)(Data* dst, const Data& src);
179 // the type info function
180 const std::type_info* ptype_info;
181 };
182 // constant to check if data can be stored on heap.
183 template<typename T>
184 struct data_on_stack {
185 static const bool value = alignof(T) <= kAlign && sizeof(T) <= kStack;
186 };
187 // declare friend with
188 template<typename T>
189 friend T& get(any& src); // NOLINT(*)
190 template<typename T>
191 friend const T& get(const any& src);
192 template<typename T>
193 friend T& unsafe_get(any& src); // NOLINT(*)
194 template<typename T>
195 friend const T& unsafe_get(const any& src);
196 // internal construct function
197 inline void construct(any&& other);
198 // internal construct function
199 inline void construct(const any& other);
200 // internal function to check if type is correct.
201 template<typename T>
202 inline void check_type() const;
203 template<typename T>
204 inline void check_type_by_name() const;
205 // internal type specific information
206 const Type* type_{nullptr};
207 // internal data
208 Data data_;
209};
210
211template<typename T>
212inline any::any(T&& other) {
213 typedef typename std::decay<T>::type DT;
214 if (std::is_same<DT, any>::value) {
215 this->construct(std::forward<T>(other));
216 } else {
217 static_assert(std::is_copy_constructible<DT>::value,
218 "Any can only hold value that is copy constructable");
219 type_ = TypeInfo<DT>::get_type();
220 if (data_on_stack<DT>::value) {
221#pragma GCC diagnostic push
222#if 6 <= __GNUC__
223#pragma GCC diagnostic ignored "-Wplacement-new"
224#endif
225 new (&(data_.stack)) DT(std::forward<T>(other));
226#pragma GCC diagnostic pop
227 } else {
228 data_.pheap = new DT(std::forward<T>(other));
229 }
230 }
231}
232
233inline any::any(any&& other) {
234 this->construct(std::move(other));
235}
236
237inline any::any(const any& other) {
238 this->construct(other);
239}
240
241inline void any::construct(any&& other) {
242 type_ = other.type_;
243 data_ = other.data_;
244 other.type_ = nullptr;
245}
246
247inline void any::construct(const any& other) {
248 type_ = other.type_;
249 if (type_ != nullptr) {
250 type_->create_from_data(&data_, other.data_);
251 }
252}
253
254template<typename T, typename... Args>
255inline void any::construct(Args&&... args) {
256 clear();
257 typedef typename std::decay<T>::type DT;
258 type_ = TypeInfo<DT>::get_type();
259 if (data_on_stack<DT>::value) {
260#pragma GCC diagnostic push
261#if 6 <= __GNUC__
262#pragma GCC diagnostic ignored "-Wplacement-new"
263#endif
264 new (&(data_.stack)) DT(std::forward<Args>(args)...);
265#pragma GCC diagnostic pop
266 } else {
267 data_.pheap = new DT(std::forward<Args>(args)...);
268 }
269}
270
271inline any::~any() {
272 this->clear();
273}
274
275inline any& any::operator=(any&& other) {
276 any(std::move(other)).swap(*this);
277 return *this;
278}
279
280inline any& any::operator=(const any& other) {
281 any(other).swap(*this);
282 return *this;
283}
284
285template<typename T>
286inline any& any::operator=(T&& other) {
287 any(std::forward<T>(other)).swap(*this);
288 return *this;
289}
290
291inline void any::swap(any& other) { // NOLINT(*)
292 std::swap(type_, other.type_);
293 std::swap(data_, other.data_);
294}
295
296inline void any::clear() {
297 if (type_ != nullptr) {
298 if (type_->destroy != nullptr) {
299 type_->destroy(&data_);
300 }
301 type_ = nullptr;
302 }
303}
304
305inline bool any::empty() const {
306 return type_ == nullptr;
307}
308
309inline const std::type_info& any::type() const {
310 if (type_ != nullptr) {
311 return *(type_->ptype_info);
312 } else {
313 return typeid(void);
314 }
315}
316
317template<typename T>
318inline void any::check_type() const {
319 CHECK(type_ != nullptr)
320 << "The any container is empty"
321 << " requested=" << typeid(T).name();
322 CHECK(*(type_->ptype_info) == typeid(T))
323 << "The stored type mismatch"
324 << " stored=" << type_->ptype_info->name()
325 << " requested=" << typeid(T).name();
326}
327
328template<typename T>
329inline void any::check_type_by_name() const {
330 CHECK(type_ != nullptr)
331 << "The any container is empty"
332 << " requested=" << typeid(T).name();
333 CHECK(strcmp(type_->ptype_info->name(), typeid(T).name()) == 0)
334 << "The stored type name mismatch"
335 << " stored=" << type_->ptype_info->name()
336 << " requested=" << typeid(T).name();
337}
338
339template<typename T>
340inline const T& get(const any& src) {
341 src.check_type<T>();
342 return *any::TypeInfo<T>::get_ptr(&(src.data_));
343}
344
345template<typename T>
346inline T& get(any& src) { // NOLINT(*)
347 src.check_type<T>();
348 return *any::TypeInfo<T>::get_ptr(&(src.data_));
349}
350
351template<typename T>
352inline const T& unsafe_get(const any& src) {
353 src.check_type_by_name<T>();
354 return *any::TypeInfo<T>::get_ptr(&(src.data_));
355}
356
357template<typename T>
358inline T& unsafe_get(any& src) { // NOLINT(*)
359 src.check_type_by_name<T>();
360 return *any::TypeInfo<T>::get_ptr(&(src.data_));
361}
362
363template<typename T>
364class any::TypeOnHeap {
365 public:
366 inline static T* get_ptr(any::Data* data) {
367 return static_cast<T*>(data->pheap);
368 }
369 inline static const T* get_ptr(const any::Data* data) {
370 return static_cast<const T*>(data->pheap);
371 }
372 inline static void create_from_data(any::Data* dst, const any::Data& data) {
373 dst->pheap = new T(*get_ptr(&data));
374 }
375 inline static void destroy(Data* data) {
376 delete static_cast<T*>(data->pheap);
377 }
378};
379
380template<typename T>
381class any::TypeOnStack {
382 public:
383 inline static T* get_ptr(any::Data* data) {
384 return reinterpret_cast<T*>(&(data->stack));
385 }
386 inline static const T* get_ptr(const any::Data* data) {
387 return reinterpret_cast<const T*>(&(data->stack));
388 }
389 inline static void create_from_data(any::Data* dst, const any::Data& data) {
390 new (&(dst->stack)) T(*get_ptr(&data));
391 }
392 inline static void destroy(Data* data) {
393 T* dptr = reinterpret_cast<T*>(&(data->stack));
394 dptr->~T();
395 }
396};
397
398template<typename T>
399class any::TypeInfo
400 : public std::conditional<any::data_on_stack<T>::value,
401 any::TypeOnStack<T>,
402 any::TypeOnHeap<T> >::type {
403 public:
404 inline static const Type* get_type() {
405 static TypeInfo<T> tp;
406 return &(tp.type_);
407 }
408
409 private:
410 // local type
411 Type type_;
412 // constructor
413 TypeInfo() {
414 if (std::is_pod<T>::value && data_on_stack<T>::value) {
415 type_.destroy = nullptr;
416 } else {
417 type_.destroy = TypeInfo<T>::destroy;
418 }
419 type_.create_from_data = TypeInfo<T>::create_from_data;
420 type_.ptype_info = &typeid(T);
421 }
422};
424
425} // namespace dmlc
426
427#endif // DMLC_ANY_H_
defines console logging options for xgboost. Use to enforce unified print behavior.
namespace for dmlc
Definition array_view.h:12
NLOHMANN_BASIC_JSON_TPL_DECLARATION void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL &j1, nlohmann::NLOHMANN_BASIC_JSON_TPL &j2) noexcept(//NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp) is_nothrow_move_constructible< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value &&//NOLINT(misc-redundant-expression) is_nothrow_move_assignable< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value)
exchanges the values of two JSON objects
Definition json.hpp:24418
Macros common to all headers.