nndeploy C++ API  0.2.0
nndeploy C++ API
any.h
Go to the documentation of this file.
1 
5 #ifndef _NNDEPLOY_BASE_Any_H_
6 #define _NNDEPLOY_BASE_Any_H_
7 
8 // This code need c++11 to compile
9 #include <algorithm>
10 #include <cstring>
11 #include <type_traits>
12 #include <typeinfo>
13 #include <utility>
14 
15 #include "nndeploy/base/common.h"
17 #include "nndeploy/base/macro.h"
18 #include "nndeploy/base/status.h"
19 
20 // 跨平台的编译器警告控制
21 #ifdef _MSC_VER
22  // MSVC: 禁用特定警告
23  #pragma warning(push)
24  #pragma warning(disable: 26439) // 禁用 C26439 警告
25  #pragma warning(push)
26  #pragma warning(disable: 4068) // 禁用 C4068 警告
27 #endif
28 
29 namespace nndeploy {
30 namespace base {
31 
32 // forward declare Any;
33 class Any;
34 
45 template <typename T>
46 inline T& get(Any& src); // NOLINT(*)
47 
58 template <typename T>
59 inline const T& get(const Any& src);
60 
71 template <typename T>
72 inline T& unsafeGet(Any& src); // NOLINT(*)
73 
84 template <typename T>
85 inline const T& unsafeGet(const Any& src);
86 
102 class Any {
103  public:
105  inline Any() = default;
110  inline Any(Any&& other); // NOLINT(*)
111 
116  inline Any(const Any& other); // NOLINT(*)
117 
123  template <typename T>
124  inline Any(T&& other); // NOLINT(*)
125 
127  inline ~Any();
128 
134  inline Any& operator=(Any&& other);
135 
141  inline Any& operator=(const Any& other);
142 
149  template <typename T>
150  inline Any& operator=(T&& other);
151 
155  inline bool empty() const;
156 
160  inline void clear();
161 
166  inline void swap(Any& other); // NOLINT(*)
167 
171  inline const std::type_info& type() const;
172 
174  template <typename T, typename... Args>
175  inline void construct(Args&&... args);
176 
177  private:
179  // declare of helper class
180  template <typename T>
181  class TypeOnHeap;
182 
183  template <typename T>
184  class TypeOnStack;
185 
186  template <typename T>
187  class TypeInfo;
188 
189  // size of stack space, it takes 32 bytes for one Any type.
190  static const size_t kStack = sizeof(void*) * 3;
191  static const size_t kAlign = sizeof(void*);
192 
193  // container use dynamic storage only when space runs lager
194  union Data {
195  // stack space
196  std::aligned_storage<kStack, kAlign>::type stack;
197  // pointer to heap space
198  void* pheap;
199  };
200 
201  // type specific information
202  struct Type {
203  // destructor function
204  void (*destroy)(Data* data);
205  // copy constructor
206  void (*createFromData)(Data* dst, const Data& src);
207  // the type info function
208  const std::type_info* ptype_info;
209  };
210 
211  // constant to check if data can be stored on heap.
212  template <typename T>
213  struct data_on_stack {
214  static const bool value = alignof(T) <= kAlign && sizeof(T) <= kStack;
215  };
216 
217  // declare friend with
218  template <typename T>
219  friend T& get(Any& src); // NOLINT(*)
220 
221  template <typename T>
222  friend const T& get(const Any& src);
223 
224  template <typename T>
225  friend T& unsafeGet(Any& src); // NOLINT(*)
226 
227  template <typename T>
228  friend const T& unsafeGet(const Any& src);
229 
230  // internal construct function
231  inline void construct(Any&& other);
232 
233  // internal construct function
234  inline void construct(const Any& other);
235 
236  // internal function to check if type is correct.
237  template <typename T>
238  inline void checkType() const;
239 
240  template <typename T>
241  inline void checkTypeByName() const;
242 
243  // internal type specific information
244  const Type* type_{nullptr};
245 
246  // internal data
247  Data data_;
248 };
249 
250 template <typename T>
251 inline Any::Any(T&& other) {
252  // 将 T 转换为其基础类型,去掉引用和常量修饰符
253  typedef typename std::decay<T>::type DT;
254  // 检查 T 是否为 Any 类型
255  if (std::is_same<DT, Any>::value) {
256  // 如果是,调用内部构造函数
257  this->construct(std::forward<T>(other));
258  } else {
259  // 确保 T 是可拷贝构造的
260  static_assert(std::is_copy_constructible<DT>::value,
261  "Any can only hold value that is copy constructable");
262  // 获取类型信息并存储
263  type_ = TypeInfo<DT>::getType();
264  // 检查是否可以在栈上存储
265  if (data_on_stack<DT>::value) {
266 #pragma GCC diagnostic push
267 #if 6 <= __GNUC__
268 #pragma GCC diagnostic ignored "-Wplacement-new"
269 #endif
270  new (&(data_.stack)) DT(std::forward<T>(other)); // 在栈上构造对象
271 #pragma GCC diagnostic pop
272  } else {
273  data_.pheap = new DT(std::forward<T>(other)); // 否则在堆上构造对象
274  }
275  }
276 }
277 
278 inline Any::Any(Any&& other) { this->construct(std::move(other)); }
279 
280 inline Any::Any(const Any& other) { this->construct(other); }
281 
282 inline void Any::construct(Any&& other) {
283  type_ = other.type_;
284  data_ = other.data_;
285  other.type_ = nullptr;
286 }
287 
288 inline void Any::construct(const Any& other) {
289  type_ = other.type_;
290  if (type_ != nullptr) {
291  type_->createFromData(&data_, other.data_);
292  }
293 }
294 
295 template <typename T, typename... Args>
296 inline void Any::construct(Args&&... args) {
297  clear();
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
302 #if 6 <= __GNUC__
303 #pragma GCC diagnostic ignored "-Wplacement-new"
304 #endif
305  new (&(data_.stack)) DT(std::forward<Args>(args)...);
306 #pragma GCC diagnostic pop
307  } else {
308  data_.pheap = new DT(std::forward<Args>(args)...);
309  }
310 }
311 
312 inline Any::~Any() { this->clear(); }
313 
314 inline Any& Any::operator=(Any&& other) {
315  Any(std::move(other)).swap(*this);
316  return *this;
317 }
318 
319 inline Any& Any::operator=(const Any& other) {
320  Any(other).swap(*this);
321  return *this;
322 }
323 
324 template <typename T>
325 inline Any& Any::operator=(T&& other) {
326  Any(std::forward<T>(other)).swap(*this);
327  return *this;
328 }
329 
330 inline void Any::swap(Any& other) { // NOLINT(*)
331  std::swap(type_, other.type_);
332  std::swap(data_, other.data_);
333 }
334 
335 inline void Any::clear() {
336  if (type_ != nullptr) {
337  if (type_->destroy != nullptr) {
338  type_->destroy(&data_);
339  }
340  type_ = nullptr;
341  }
342 }
343 
344 inline bool Any::empty() const { return type_ == nullptr; }
345 
346 inline const std::type_info& Any::type() const {
347  if (type_ != nullptr) {
348  return *(type_->ptype_info);
349  } else {
350  return typeid(void);
351  }
352 }
353 
354 template <typename T>
355 inline void Any::checkType() const {
356  if (type_ == nullptr) {
357  NNDEPLOY_LOGE("The Any container is empty\n");
358  NNDEPLOY_LOGE(" requested=%s\n", typeid(T).name());
359  assert(false);
360  }
361  if (*(type_->ptype_info) != typeid(T)) {
362  NNDEPLOY_LOGE("The stored type mismatch\n");
363  NNDEPLOY_LOGE(" stored=%s\n", type_->ptype_info->name());
364  NNDEPLOY_LOGE(" requested=%s\n", typeid(T).name());
365  assert(false);
366  }
367 }
368 
369 template <typename T>
370 inline void Any::checkTypeByName() const {
371  if (type_ == nullptr) {
372  NNDEPLOY_LOGE("The Any container is empty\n");
373  NNDEPLOY_LOGE(" requested=%s\n", typeid(T).name());
374  assert(false);
375  }
376  if (strcmp(type_->ptype_info->name(), typeid(T).name()) != 0) {
377  NNDEPLOY_LOGE("The stored type name mismatch\n");
378  NNDEPLOY_LOGE(" stored=%s\n", type_->ptype_info->name());
379  NNDEPLOY_LOGE(" requested=%s\n", typeid(T).name());
380  assert(false);
381  }
382 }
383 
384 template <typename T>
385 inline const T& get(const Any& src) {
386  src.checkType<T>();
387  return *Any::TypeInfo<T>::getPtr(&(src.data_));
388 }
389 
390 template <typename T>
391 inline T& get(Any& src) { // NOLINT(*)
392  src.checkType<T>();
393  return *Any::TypeInfo<T>::getPtr(&(src.data_));
394 }
395 
396 template <typename T>
397 inline const T& unsafeGet(const Any& src) {
398  src.checkTypeByName<T>();
399  return *Any::TypeInfo<T>::getPtr(&(src.data_));
400 }
401 
402 template <typename T>
403 inline T& unsafeGet(Any& src) { // NOLINT(*)
404  src.checkTypeByName<T>();
405  return *Any::TypeInfo<T>::getPtr(&(src.data_));
406 }
407 
408 template <typename T>
409 class Any::TypeOnHeap {
410  public:
411  inline static T* getPtr(Any::Data* data) {
412  return static_cast<T*>(data->pheap);
413  }
414  inline static const T* getPtr(const Any::Data* data) {
415  return static_cast<const T*>(data->pheap);
416  }
417  inline static void createFromData(Any::Data* dst, const Any::Data& data) {
418  dst->pheap = new T(*getPtr(&data));
419  }
420  inline static void destroy(Data* data) {
421  delete static_cast<T*>(data->pheap);
422  }
423 };
424 
425 template <typename T>
426 class Any::TypeOnStack {
427  public:
428  inline static T* getPtr(Any::Data* data) {
429  return reinterpret_cast<T*>(&(data->stack));
430  }
431  inline static const T* getPtr(const Any::Data* data) {
432  return reinterpret_cast<const T*>(&(data->stack));
433  }
434  inline static void createFromData(Any::Data* dst, const Any::Data& data) {
435  new (&(dst->stack)) T(*getPtr(&data));
436  }
437  inline static void destroy(Data* data) {
438  T* dptr = reinterpret_cast<T*>(&(data->stack));
439  dptr->~T();
440  }
441 };
442 
443 template <typename T>
444 class Any::TypeInfo
445  : public std::conditional<Any::data_on_stack<T>::value, Any::TypeOnStack<T>,
446  Any::TypeOnHeap<T> >::type {
447  public:
448  inline static const Type* getType() {
449  static TypeInfo<T> tp;
450  return &(tp.type_);
451  }
452 
453  private:
454  // local type
455  Type type_;
456  // constructor
457  TypeInfo() {
458  if (std::is_pod<T>::value && data_on_stack<T>::value) {
459  type_.destroy = nullptr;
460  } else {
461  type_.destroy = TypeInfo<T>::destroy;
462  }
463  type_.createFromData = TypeInfo<T>::createFromData;
464  type_.ptype_info = &typeid(T);
465  }
466 };
467 
468 } // namespace base
469 } // namespace nndeploy
470 
471 // 恢复警告状态(仅对MSVC生效)
472 #ifdef _MSC_VER
473  #pragma warning(pop) // 恢复之前的警告状态
474  #pragma warning(pop) // 恢复之前的警告状态
475 #endif
476 
477 #endif
#define NNDEPLOY_LOGE(fmt,...)
Definition: log.h:59