5 #ifndef _NNDEPLOY_BASE_Any_H_
6 #define _NNDEPLOY_BASE_Any_H_
11 #include <type_traits>
24 #pragma warning(disable: 26439)
26 #pragma warning(disable: 4068)
46 inline T& get(Any& src);
59 inline const T& get(
const Any& src);
72 inline T& unsafeGet(Any& src);
85 inline const T& unsafeGet(
const Any& src);
105 inline Any() =
default;
110 inline Any(Any&& other);
116 inline Any(
const Any& other);
123 template <
typename T>
124 inline Any(T&& other);
134 inline Any& operator=(Any&& other);
141 inline Any& operator=(
const Any& other);
149 template <
typename T>
150 inline Any& operator=(T&& other);
155 inline bool empty()
const;
166 inline void swap(Any& other);
171 inline const std::type_info& type()
const;
174 template <
typename T,
typename... Args>
175 inline void construct(Args&&... args);
180 template <
typename T>
183 template <
typename T>
186 template <
typename T>
190 static const size_t kStack =
sizeof(
void*) * 3;
191 static const size_t kAlign =
sizeof(
void*);
196 std::aligned_storage<kStack, kAlign>::type stack;
204 void (*destroy)(Data* data);
206 void (*createFromData)(Data* dst,
const Data& src);
208 const std::type_info* ptype_info;
212 template <
typename T>
213 struct data_on_stack {
214 static const bool value =
alignof(T) <= kAlign &&
sizeof(T) <= kStack;
218 template <
typename T>
219 friend T& get(Any& src);
221 template <
typename T>
222 friend const T& get(
const Any& src);
224 template <
typename T>
225 friend T& unsafeGet(Any& src);
227 template <
typename T>
228 friend const T& unsafeGet(
const Any& src);
231 inline void construct(Any&& other);
234 inline void construct(
const Any& other);
237 template <
typename T>
238 inline void checkType()
const;
240 template <
typename T>
241 inline void checkTypeByName()
const;
244 const Type* type_{
nullptr};
250 template <
typename T>
251 inline Any::Any(T&& other) {
253 typedef typename std::decay<T>::type DT;
255 if (std::is_same<DT, Any>::value) {
257 this->construct(std::forward<T>(other));
260 static_assert(std::is_copy_constructible<DT>::value,
261 "Any can only hold value that is copy constructable");
263 type_ = TypeInfo<DT>::getType();
265 if (data_on_stack<DT>::value) {
266 #pragma GCC diagnostic push
268 #pragma GCC diagnostic ignored "-Wplacement-new"
270 new (&(data_.stack)) DT(std::forward<T>(other));
271 #pragma GCC diagnostic pop
273 data_.pheap =
new DT(std::forward<T>(other));
278 inline Any::Any(Any&& other) { this->construct(std::move(other)); }
280 inline Any::Any(
const Any& other) { this->construct(other); }
282 inline void Any::construct(Any&& other) {
285 other.type_ =
nullptr;
288 inline void Any::construct(
const Any& other) {
290 if (type_ !=
nullptr) {
291 type_->createFromData(&data_, other.data_);
295 template <
typename T,
typename... Args>
296 inline void Any::construct(Args&&... args) {
298 typedef typename std::decay<T>::type DT;
299 type_ = TypeInfo<DT>::getType();
300 if (data_on_stack<DT>::value) {
301 #pragma GCC diagnostic push
303 #pragma GCC diagnostic ignored "-Wplacement-new"
305 new (&(data_.stack)) DT(std::forward<Args>(args)...);
306 #pragma GCC diagnostic pop
308 data_.pheap =
new DT(std::forward<Args>(args)...);
312 inline Any::~Any() { this->clear(); }
314 inline Any& Any::operator=(Any&& other) {
315 Any(std::move(other)).swap(*
this);
319 inline Any& Any::operator=(
const Any& other) {
320 Any(other).swap(*
this);
324 template <
typename T>
325 inline Any& Any::operator=(T&& other) {
326 Any(std::forward<T>(other)).swap(*
this);
330 inline void Any::swap(Any& other) {
331 std::swap(type_, other.type_);
332 std::swap(data_, other.data_);
335 inline void Any::clear() {
336 if (type_ !=
nullptr) {
337 if (type_->destroy !=
nullptr) {
338 type_->destroy(&data_);
344 inline bool Any::empty()
const {
return type_ ==
nullptr; }
346 inline const std::type_info& Any::type()
const {
347 if (type_ !=
nullptr) {
348 return *(type_->ptype_info);
354 template <
typename T>
355 inline void Any::checkType()
const {
356 if (type_ ==
nullptr) {
361 if (*(type_->ptype_info) !=
typeid(T)) {
369 template <
typename T>
370 inline void Any::checkTypeByName()
const {
371 if (type_ ==
nullptr) {
376 if (strcmp(type_->ptype_info->name(),
typeid(T).name()) != 0) {
384 template <
typename T>
385 inline const T& get(
const Any& src) {
387 return *Any::TypeInfo<T>::getPtr(&(src.data_));
390 template <
typename T>
391 inline T& get(Any& src) {
393 return *Any::TypeInfo<T>::getPtr(&(src.data_));
396 template <
typename T>
397 inline const T& unsafeGet(
const Any& src) {
398 src.checkTypeByName<T>();
399 return *Any::TypeInfo<T>::getPtr(&(src.data_));
402 template <
typename T>
403 inline T& unsafeGet(Any& src) {
404 src.checkTypeByName<T>();
405 return *Any::TypeInfo<T>::getPtr(&(src.data_));
408 template <
typename T>
409 class Any::TypeOnHeap {
411 inline static T* getPtr(Any::Data* data) {
412 return static_cast<T*
>(data->pheap);
414 inline static const T* getPtr(
const Any::Data* data) {
415 return static_cast<const T*
>(data->pheap);
417 inline static void createFromData(Any::Data* dst,
const Any::Data& data) {
418 dst->pheap =
new T(*getPtr(&data));
420 inline static void destroy(Data* data) {
421 delete static_cast<T*
>(data->pheap);
425 template <
typename T>
426 class Any::TypeOnStack {
428 inline static T* getPtr(Any::Data* data) {
429 return reinterpret_cast<T*
>(&(data->stack));
431 inline static const T* getPtr(
const Any::Data* data) {
432 return reinterpret_cast<const T*
>(&(data->stack));
434 inline static void createFromData(Any::Data* dst,
const Any::Data& data) {
435 new (&(dst->stack)) T(*getPtr(&data));
437 inline static void destroy(Data* data) {
438 T* dptr =
reinterpret_cast<T*
>(&(data->stack));
443 template <
typename T>
445 :
public std::conditional<Any::data_on_stack<T>::value, Any::TypeOnStack<T>,
446 Any::TypeOnHeap<T> >::type {
448 inline static const Type* getType() {
449 static TypeInfo<T> tp;
458 if (std::is_pod<T>::value && data_on_stack<T>::value) {
459 type_.destroy =
nullptr;
461 type_.destroy = TypeInfo<T>::destroy;
463 type_.createFromData = TypeInfo<T>::createFromData;
464 type_.ptype_info = &
typeid(T);
#define NNDEPLOY_LOGE(fmt,...)