11 #include <type_traits> 17 #include "./logging.h" 34 inline T&
get(any& src);
47 inline const T&
get(
const any& src);
60 inline const T& unsafe_get(
const any& src);
73 inline T& unsafe_get(any& src);
93 inline any() =
default;
98 inline any(any&& other);
103 inline any(
const any& other);
110 inline any(T&& other);
118 inline any& operator=(any&& other);
124 inline any& operator=(
const any& other);
132 inline any& operator=(T&& other);
136 inline bool empty()
const;
145 inline void swap(any& other);
149 inline const std::type_info& type()
const;
151 template<
typename T,
typename... Args>
152 inline void construct(Args&&... args);
164 static const size_t kStack =
sizeof(
void*) * 3;
165 static const size_t kAlign =
sizeof(
void*);
169 std::aligned_storage<kStack, kAlign>::type stack;
176 void (*destroy)(Data* data);
178 void (*create_from_data)(Data* dst,
const Data& src);
180 const std::type_info* ptype_info;
184 struct data_on_stack {
185 static const bool value =
alignof(T) <= kAlign &&
sizeof(T) <= kStack;
189 friend T&
get(any& src);
191 friend const T&
get(
const any& src);
193 friend T& unsafe_get(any& src);
195 friend const T& unsafe_get(
const any& src);
197 inline void construct(any&& other);
199 inline void construct(
const any& other);
202 inline void check_type()
const;
204 inline void check_type_by_name()
const;
206 const Type* type_{
nullptr};
212 inline 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));
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 223 #pragma GCC diagnostic ignored "-Wplacement-new" 225 new (&(data_.stack)) DT(std::forward<T>(other));
226 #pragma GCC diagnostic pop 228 data_.pheap =
new DT(std::forward<T>(other));
233 inline any::any(any&& other) {
234 this->construct(std::move(other));
237 inline any::any(
const any& other) {
238 this->construct(other);
241 inline void any::construct(any&& other) {
244 other.type_ =
nullptr;
247 inline void any::construct(
const any& other) {
249 if (type_ !=
nullptr) {
250 type_->create_from_data(&data_, other.data_);
254 template<
typename T,
typename... Args>
255 inline void any::construct(Args&&... args) {
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 262 #pragma GCC diagnostic ignored "-Wplacement-new" 264 new (&(data_.stack)) DT(std::forward<Args>(args)...);
265 #pragma GCC diagnostic pop 267 data_.pheap =
new DT(std::forward<Args>(args)...);
275 inline any& any::operator=(any&& other) {
276 any(std::move(other)).swap(*
this);
280 inline any& any::operator=(
const any& other) {
281 any(other).swap(*
this);
286 inline any& any::operator=(T&& other) {
287 any(std::forward<T>(other)).swap(*
this);
291 inline void any::swap(any& other) {
292 std::swap(type_, other.type_);
293 std::swap(data_, other.data_);
296 inline void any::clear() {
297 if (type_ !=
nullptr) {
298 if (type_->destroy !=
nullptr) {
299 type_->destroy(&data_);
305 inline bool any::empty()
const {
306 return type_ ==
nullptr;
309 inline const std::type_info& any::type()
const {
310 if (type_ !=
nullptr) {
311 return *(type_->ptype_info);
318 inline 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();
329 inline 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();
340 inline const T&
get(
const any& src) {
342 return *any::TypeInfo<T>::get_ptr(&(src.data_));
346 inline T&
get(any& src) {
348 return *any::TypeInfo<T>::get_ptr(&(src.data_));
352 inline const T& unsafe_get(
const any& src) {
353 src.check_type_by_name<T>();
354 return *any::TypeInfo<T>::get_ptr(&(src.data_));
358 inline T& unsafe_get(any& src) {
359 src.check_type_by_name<T>();
360 return *any::TypeInfo<T>::get_ptr(&(src.data_));
364 class any::TypeOnHeap {
366 inline static T* get_ptr(any::Data* data) {
367 return static_cast<T*
>(data->pheap);
369 inline static const T* get_ptr(
const any::Data* data) {
370 return static_cast<const T*
>(data->pheap);
372 inline static void create_from_data(any::Data* dst,
const any::Data& data) {
373 dst->pheap =
new T(*get_ptr(&data));
375 inline static void destroy(Data* data) {
376 delete static_cast<T*
>(data->pheap);
381 class any::TypeOnStack {
383 inline static T* get_ptr(any::Data* data) {
384 return reinterpret_cast<T*
>(&(data->stack));
386 inline static const T* get_ptr(
const any::Data* data) {
387 return reinterpret_cast<const T*
>(&(data->stack));
389 inline static void create_from_data(any::Data* dst,
const any::Data& data) {
390 new (&(dst->stack)) T(*get_ptr(&data));
392 inline static void destroy(Data* data) {
393 T* dptr =
reinterpret_cast<T*
>(&(data->stack));
400 :
public std::conditional<any::data_on_stack<T>::value,
402 any::TypeOnHeap<T> >::type {
404 inline static const Type* get_type() {
405 static TypeInfo<T> tp;
414 if (std::is_pod<T>::value && data_on_stack<T>::value) {
415 type_.destroy =
nullptr;
417 type_.destroy = TypeInfo<T>::destroy;
419 type_.create_from_data = TypeInfo<T>::create_from_data;
420 type_.ptype_info = &
typeid(T);
427 #endif // DMLC_ANY_H_ namespace for dmlc
Definition: array_view.h:12