Blender  V3.3
BLI_cpp_type.hh
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #pragma once
4 
73 #include "BLI_hash.hh"
74 #include "BLI_index_mask.hh"
75 #include "BLI_map.hh"
76 #include "BLI_math_base.h"
77 #include "BLI_string_ref.hh"
78 #include "BLI_utility_mixins.hh"
79 
85 enum class CPPTypeFlags {
86  None = 0,
87  Hashable = 1 << 0,
88  Printable = 1 << 1,
89  EqualityComparable = 1 << 2,
90 
92 };
94 
95 namespace blender {
96 
98 template<typename T, CPPTypeFlags Flags> struct CPPTypeParam {
99 };
100 
102  private:
103  int64_t size_ = 0;
104  int64_t alignment_ = 0;
105  uintptr_t alignment_mask_ = 0;
106  bool is_trivial_ = false;
107  bool is_trivially_destructible_ = false;
108  bool has_special_member_functions_ = false;
109 
110  void (*default_construct_)(void *ptr) = nullptr;
111  void (*default_construct_indices_)(void *ptr, IndexMask mask) = nullptr;
112 
113  void (*value_initialize_)(void *ptr) = nullptr;
114  void (*value_initialize_indices_)(void *ptr, IndexMask mask) = nullptr;
115 
116  void (*destruct_)(void *ptr) = nullptr;
117  void (*destruct_indices_)(void *ptr, IndexMask mask) = nullptr;
118 
119  void (*copy_assign_)(const void *src, void *dst) = nullptr;
120  void (*copy_assign_indices_)(const void *src, void *dst, IndexMask mask) = nullptr;
121  void (*copy_assign_compressed_)(const void *src, void *dst, IndexMask mask) = nullptr;
122 
123  void (*copy_construct_)(const void *src, void *dst) = nullptr;
124  void (*copy_construct_indices_)(const void *src, void *dst, IndexMask mask) = nullptr;
125  void (*copy_construct_compressed_)(const void *src, void *dst, IndexMask mask) = nullptr;
126 
127  void (*move_assign_)(void *src, void *dst) = nullptr;
128  void (*move_assign_indices_)(void *src, void *dst, IndexMask mask) = nullptr;
129 
130  void (*move_construct_)(void *src, void *dst) = nullptr;
131  void (*move_construct_indices_)(void *src, void *dst, IndexMask mask) = nullptr;
132 
133  void (*relocate_assign_)(void *src, void *dst) = nullptr;
134  void (*relocate_assign_indices_)(void *src, void *dst, IndexMask mask) = nullptr;
135 
136  void (*relocate_construct_)(void *src, void *dst) = nullptr;
137  void (*relocate_construct_indices_)(void *src, void *dst, IndexMask mask) = nullptr;
138 
139  void (*fill_assign_indices_)(const void *value, void *dst, IndexMask mask) = nullptr;
140 
141  void (*fill_construct_indices_)(const void *value, void *dst, IndexMask mask) = nullptr;
142 
143  void (*print_)(const void *value, std::stringstream &ss) = nullptr;
144  bool (*is_equal_)(const void *a, const void *b) = nullptr;
145  uint64_t (*hash_)(const void *value) = nullptr;
146 
147  const void *default_value_ = nullptr;
148  std::string debug_name_;
149 
150  public:
151  template<typename T, CPPTypeFlags Flags> CPPType(CPPTypeParam<T, Flags>, StringRef debug_name);
152  virtual ~CPPType() = default;
153 
158  friend bool operator==(const CPPType &a, const CPPType &b)
159  {
160  return &a == &b;
161  }
162 
163  friend bool operator!=(const CPPType &a, const CPPType &b)
164  {
165  return !(&a == &b);
166  }
167 
173  template<typename T> static const CPPType &get()
174  {
175  /* Store the #CPPType locally to avoid making the function call in most cases. */
176  static const CPPType &type = CPPType::get_impl<std::remove_cv_t<T>>();
177  return type;
178  }
179  template<typename T> static const CPPType &get_impl();
180 
186  {
187  return debug_name_;
188  }
189 
196  int64_t size() const
197  {
198  return size_;
199  }
200 
208  {
209  return alignment_;
210  }
211 
220  {
221  return is_trivially_destructible_;
222  }
223 
231  bool is_trivial() const
232  {
233  return is_trivial_;
234  }
235 
237  {
238  return default_construct_ != nullptr;
239  }
240 
242  {
243  return copy_assign_ != nullptr;
244  }
245 
247  {
248  return move_assign_ != nullptr;
249  }
250 
251  bool is_destructible() const
252  {
253  return destruct_ != nullptr;
254  }
255 
256  bool is_copy_assignable() const
257  {
258  return copy_assign_ != nullptr;
259  }
260 
261  bool is_move_assignable() const
262  {
263  return copy_construct_ != nullptr;
264  }
265 
266  bool is_printable() const
267  {
268  return print_ != nullptr;
269  }
270 
272  {
273  return is_equal_ != nullptr;
274  }
275 
276  bool is_hashable() const
277  {
278  return hash_ != nullptr;
279  }
280 
291  {
292  return has_special_member_functions_;
293  }
294 
298  bool pointer_has_valid_alignment(const void *ptr) const
299  {
300  return ((uintptr_t)ptr & alignment_mask_) == 0;
301  }
302 
303  bool pointer_can_point_to_instance(const void *ptr) const
304  {
305  return ptr != nullptr && pointer_has_valid_alignment(ptr);
306  }
307 
316  void default_construct(void *ptr) const
317  {
319 
320  default_construct_(ptr);
321  }
322 
323  void default_construct_n(void *ptr, int64_t n) const
324  {
325  this->default_construct_indices(ptr, IndexMask(n));
326  }
327 
329  {
330  BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(ptr));
331 
332  default_construct_indices_(ptr, mask);
333  }
334 
341  void value_initialize(void *ptr) const
342  {
344 
345  value_initialize_(ptr);
346  }
347 
348  void value_initialize_n(void *ptr, int64_t n) const
349  {
350  this->value_initialize_indices(ptr, IndexMask(n));
351  }
352 
354  {
355  BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(ptr));
356 
357  value_initialize_indices_(ptr, mask);
358  }
359 
368  void destruct(void *ptr) const
369  {
371 
372  destruct_(ptr);
373  }
374 
375  void destruct_n(void *ptr, int64_t n) const
376  {
377  this->destruct_indices(ptr, IndexMask(n));
378  }
379 
380  void destruct_indices(void *ptr, IndexMask mask) const
381  {
382  BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(ptr));
383 
384  destruct_indices_(ptr, mask);
385  }
386 
393  void copy_assign(const void *src, void *dst) const
394  {
397 
398  copy_assign_(src, dst);
399  }
400 
401  void copy_assign_n(const void *src, void *dst, int64_t n) const
402  {
403  this->copy_assign_indices(src, dst, IndexMask(n));
404  }
405 
406  void copy_assign_indices(const void *src, void *dst, IndexMask mask) const
407  {
408  BLI_assert(mask.size() == 0 || src != dst);
409  BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(src));
410  BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(dst));
411 
412  copy_assign_indices_(src, dst, mask);
413  }
414 
418  void copy_assign_compressed(const void *src, void *dst, IndexMask mask) const
419  {
420  BLI_assert(mask.size() == 0 || src != dst);
421  BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(src));
422  BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(dst));
423 
424  copy_assign_compressed_(src, dst, mask);
425  }
426 
435  void copy_construct(const void *src, void *dst) const
436  {
437  BLI_assert(src != dst || is_trivial_);
440 
441  copy_construct_(src, dst);
442  }
443 
444  void copy_construct_n(const void *src, void *dst, int64_t n) const
445  {
446  this->copy_construct_indices(src, dst, IndexMask(n));
447  }
448 
449  void copy_construct_indices(const void *src, void *dst, IndexMask mask) const
450  {
451  BLI_assert(mask.size() == 0 || src != dst);
452  BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(src));
453  BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(dst));
454 
455  copy_construct_indices_(src, dst, mask);
456  }
457 
461  void copy_construct_compressed(const void *src, void *dst, IndexMask mask) const
462  {
463  BLI_assert(mask.size() == 0 || src != dst);
464  BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(src));
465  BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(dst));
466 
467  copy_construct_compressed_(src, dst, mask);
468  }
469 
478  void move_assign(void *src, void *dst) const
479  {
482 
483  move_assign_(src, dst);
484  }
485 
486  void move_assign_n(void *src, void *dst, int64_t n) const
487  {
488  this->move_assign_indices(src, dst, IndexMask(n));
489  }
490 
491  void move_assign_indices(void *src, void *dst, IndexMask mask) const
492  {
493  BLI_assert(mask.size() == 0 || src != dst);
494  BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(src));
495  BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(dst));
496 
497  move_assign_indices_(src, dst, mask);
498  }
499 
508  void move_construct(void *src, void *dst) const
509  {
510  BLI_assert(src != dst || is_trivial_);
513 
514  move_construct_(src, dst);
515  }
516 
517  void move_construct_n(void *src, void *dst, int64_t n) const
518  {
519  this->move_construct_indices(src, dst, IndexMask(n));
520  }
521 
522  void move_construct_indices(void *src, void *dst, IndexMask mask) const
523  {
524  BLI_assert(mask.size() == 0 || src != dst);
525  BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(src));
526  BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(dst));
527 
528  move_construct_indices_(src, dst, mask);
529  }
530 
539  void relocate_assign(void *src, void *dst) const
540  {
541  BLI_assert(src != dst || is_trivial_);
544 
545  relocate_assign_(src, dst);
546  }
547 
548  void relocate_assign_n(void *src, void *dst, int64_t n) const
549  {
550  this->relocate_assign_indices(src, dst, IndexMask(n));
551  }
552 
553  void relocate_assign_indices(void *src, void *dst, IndexMask mask) const
554  {
555  BLI_assert(mask.size() == 0 || src != dst);
556  BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(src));
557  BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(dst));
558 
559  relocate_assign_indices_(src, dst, mask);
560  }
561 
570  void relocate_construct(void *src, void *dst) const
571  {
572  BLI_assert(src != dst || is_trivial_);
575 
576  relocate_construct_(src, dst);
577  }
578 
579  void relocate_construct_n(void *src, void *dst, int64_t n) const
580  {
581  this->relocate_construct_indices(src, dst, IndexMask(n));
582  }
583 
584  void relocate_construct_indices(void *src, void *dst, IndexMask mask) const
585  {
586  BLI_assert(mask.size() == 0 || src != dst);
587  BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(src));
588  BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(dst));
589 
590  relocate_construct_indices_(src, dst, mask);
591  }
592 
598  void fill_assign_n(const void *value, void *dst, int64_t n) const
599  {
600  this->fill_assign_indices(value, dst, IndexMask(n));
601  }
602 
603  void fill_assign_indices(const void *value, void *dst, IndexMask mask) const
604  {
605  BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(value));
606  BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(dst));
607 
608  fill_assign_indices_(value, dst, mask);
609  }
610 
616  void fill_construct_n(const void *value, void *dst, int64_t n) const
617  {
618  this->fill_construct_indices(value, dst, IndexMask(n));
619  }
620 
621  void fill_construct_indices(const void *value, void *dst, IndexMask mask) const
622  {
623  BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(value));
624  BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(dst));
625 
626  fill_construct_indices_(value, dst, mask);
627  }
628 
629  bool can_exist_in_buffer(const int64_t buffer_size, const int64_t buffer_alignment) const
630  {
631  return size_ <= buffer_size && alignment_ <= buffer_alignment;
632  }
633 
634  void print(const void *value, std::stringstream &ss) const
635  {
637  print_(value, ss);
638  }
639 
640  std::string to_string(const void *value) const
641  {
642  std::stringstream ss;
643  this->print(value, ss);
644  return ss.str();
645  }
646 
647  void print_or_default(const void *value, std::stringstream &ss, StringRef default_value) const
648  {
649  if (this->is_printable()) {
650  this->print(value, ss);
651  }
652  else {
653  ss << default_value;
654  }
655  }
656 
657  bool is_equal(const void *a, const void *b) const
658  {
661  return is_equal_(a, b);
662  }
663 
664  bool is_equal_or_false(const void *a, const void *b) const
665  {
666  if (this->is_equality_comparable()) {
667  return this->is_equal(a, b);
668  }
669  return false;
670  }
671 
672  uint64_t hash(const void *value) const
673  {
675  return hash_(value);
676  }
677 
678  uint64_t hash_or_fallback(const void *value, uint64_t fallback_hash) const
679  {
680  if (this->is_hashable()) {
681  return this->hash(value);
682  }
683  return fallback_hash;
684  }
685 
690  const void *default_value() const
691  {
692  return default_value_;
693  }
694 
695  uint64_t hash() const
696  {
697  return get_default_hash(this);
698  }
699 
700  void (*destruct_fn() const)(void *)
701  {
702  return destruct_;
703  }
704 
705  template<typename T> bool is() const
706  {
707  return this == &CPPType::get<std::decay_t<T>>();
708  }
709 
720  template<typename... Types, typename Fn> void to_static_type(const Fn &fn) const
721  {
722  using Callback = void (*)(const Fn &fn);
723 
724  /* Build a lookup table to avoid having to compare the current #CPPType with every type in
725  * #Types one after another. */
726  static const Map<const CPPType *, Callback> callback_map = []() {
727  Map<const CPPType *, Callback> callback_map;
728  /* This adds an entry in the map for every type in #Types. */
729  (callback_map.add_new(&CPPType::get<Types>(),
730  [](const Fn &fn) {
731  /* Call the templated `operator()` of the given function object. */
732  fn.template operator()<Types>();
733  }),
734  ...);
735  return callback_map;
736  }();
737 
738  const Callback callback = callback_map.lookup_default(this, nullptr);
739  if (callback != nullptr) {
740  callback(fn);
741  }
742  else {
743  /* Call the non-templated `operator()` of the given function object. */
744  fn();
745  }
746  }
747 
748  template<typename T> struct type_tag {
749  using type = T;
750  };
751 
752  private:
753  template<typename Fn> struct TypeTagExecutor {
754  const Fn &fn;
755 
756  template<typename T> void operator()() const
757  {
758  fn(type_tag<T>{});
759  }
760 
761  void operator()() const
762  {
763  fn(type_tag<void>{});
764  }
765  };
766 
767  public:
775  template<typename... Types, typename Fn> void to_static_type_tag(const Fn &fn) const
776  {
777  TypeTagExecutor<Fn> executor{fn};
778  this->to_static_type<Types...>(executor);
779  }
780 };
781 
782 } // namespace blender
783 
784 /* Utility for allocating an uninitialized buffer for a single value of the given #CPPType. */
785 #define BUFFER_FOR_CPP_TYPE_VALUE(type, variable_name) \
786  blender::DynamicStackBuffer<64, 64> stack_buffer_for_##variable_name((type).size(), \
787  (type).alignment()); \
788  void *variable_name = stack_buffer_for_##variable_name.buffer();
#define BLI_assert(a)
Definition: BLI_assert.h:46
CPPTypeFlags
Definition: BLI_cpp_type.hh:85
#define ENUM_OPERATORS(_type, _max)
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
SIMD_FORCE_INLINE btVector3 operator()(const btVector3 &x) const
Return the transform of the vector.
Definition: btTransform.h:90
void destruct_indices(void *ptr, IndexMask mask) const
void relocate_construct_indices(void *src, void *dst, IndexMask mask) const
bool is_copy_constructible() const
void copy_construct_n(const void *src, void *dst, int64_t n) const
void(*)(void *) destruct_fn() const
bool is_trivial() const
void value_initialize_indices(void *ptr, IndexMask mask) const
void to_static_type(const Fn &fn) const
void default_construct_n(void *ptr, int64_t n) const
void fill_assign_indices(const void *value, void *dst, IndexMask mask) const
virtual ~CPPType()=default
void destruct_n(void *ptr, int64_t n) const
void move_construct_n(void *src, void *dst, int64_t n) const
void default_construct_indices(void *ptr, IndexMask mask) const
void fill_assign_n(const void *value, void *dst, int64_t n) const
uint64_t hash_or_fallback(const void *value, uint64_t fallback_hash) const
bool is_equal(const void *a, const void *b) const
void copy_assign_indices(const void *src, void *dst, IndexMask mask) const
void relocate_assign_n(void *src, void *dst, int64_t n) const
uint64_t hash() const
void move_assign(void *src, void *dst) const
bool is_printable() const
std::string to_string(const void *value) const
void fill_construct_n(const void *value, void *dst, int64_t n) const
bool is_move_assignable() const
bool is_hashable() const
void relocate_construct(void *src, void *dst) const
void move_assign_n(void *src, void *dst, int64_t n) const
bool is_equal_or_false(const void *a, const void *b) const
bool has_special_member_functions() const
friend bool operator!=(const CPPType &a, const CPPType &b)
StringRefNull name() const
static const CPPType & get()
bool is() const
void copy_assign_n(const void *src, void *dst, int64_t n) const
bool is_equality_comparable() const
void value_initialize_n(void *ptr, int64_t n) const
void copy_construct_compressed(const void *src, void *dst, IndexMask mask) const
void copy_assign_compressed(const void *src, void *dst, IndexMask mask) const
uint64_t hash(const void *value) const
CPPType(CPPTypeParam< T, Flags >, StringRef debug_name)
void copy_construct(const void *src, void *dst) const
void destruct(void *ptr) const
bool pointer_has_valid_alignment(const void *ptr) const
bool is_default_constructible() const
int64_t size() const
void fill_construct_indices(const void *value, void *dst, IndexMask mask) const
bool is_copy_assignable() const
int64_t alignment() const
bool is_destructible() const
bool is_move_constructible() const
void print_or_default(const void *value, std::stringstream &ss, StringRef default_value) const
void copy_assign(const void *src, void *dst) const
static const CPPType & get_impl()
void to_static_type_tag(const Fn &fn) const
void move_construct(void *src, void *dst) const
bool can_exist_in_buffer(const int64_t buffer_size, const int64_t buffer_alignment) const
void relocate_assign_indices(void *src, void *dst, IndexMask mask) const
void print(const void *value, std::stringstream &ss) const
const void * default_value() const
bool pointer_can_point_to_instance(const void *ptr) const
void relocate_construct_n(void *src, void *dst, int64_t n) const
bool is_trivially_destructible() const
void move_assign_indices(void *src, void *dst, IndexMask mask) const
void relocate_assign(void *src, void *dst) const
void default_construct(void *ptr) const
friend bool operator==(const CPPType &a, const CPPType &b)
void value_initialize(void *ptr) const
void move_construct_indices(void *src, void *dst, IndexMask mask) const
void copy_construct_indices(const void *src, void *dst, IndexMask mask) const
Value lookup_default(const Key &key, const Value &default_value) const
Definition: BLI_map.hh:510
void add_new(const Key &key, const Value &value)
Definition: BLI_map.hh:220
DEGForeachIDComponentCallback callback
SyclQueue void void * src
SyclQueue void void size_t num_bytes void
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)
Definition: math_float4.h:513
#define T
static unsigned a[3]
Definition: RandGen.cpp:78
uint64_t get_default_hash(const T &v)
Definition: BLI_hash.hh:218
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
_W64 unsigned int uintptr_t
Definition: stdint.h:119
__int64 int64_t
Definition: stdint.h:89
unsigned __int64 uint64_t
Definition: stdint.h:90
PointerRNA * ptr
Definition: wm_files.c:3480