Blender V5.0
BLI_cpp_type.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#pragma once
6
74
75#include "BLI_hash.hh"
76#include "BLI_index_mask_fwd.hh"
77#include "BLI_map.hh"
79#include "BLI_string_ref.hh"
80#include "BLI_utility_mixins.hh"
81
97
98namespace blender {
99
101 public:
109
117
125 bool is_trivial = false;
126
135
146
150 bool is_destructible = false;
151 bool is_copy_assignable = false;
152 bool is_move_assignable = false;
153
154 private:
155 uintptr_t alignment_mask_ = 0;
156
157 void (*default_construct_)(void *ptr) = nullptr;
158 void (*default_construct_n_)(void *ptr, int64_t n) = nullptr;
159 void (*default_construct_indices_)(void *ptr, const IndexMask &mask) = nullptr;
160
161 void (*value_initialize_)(void *ptr) = nullptr;
162 void (*value_initialize_n_)(void *ptr, int64_t n) = nullptr;
163 void (*value_initialize_indices_)(void *ptr, const IndexMask &mask) = nullptr;
164
165 void (*destruct_)(void *ptr) = nullptr;
166 void (*destruct_n_)(void *ptr, int64_t n) = nullptr;
167 void (*destruct_indices_)(void *ptr, const IndexMask &mask) = nullptr;
168
169 void (*copy_assign_)(const void *src, void *dst) = nullptr;
170 void (*copy_assign_n_)(const void *src, void *dst, int64_t n) = nullptr;
171 void (*copy_assign_indices_)(const void *src, void *dst, const IndexMask &mask) = nullptr;
172 void (*copy_assign_compressed_)(const void *src, void *dst, const IndexMask &mask) = nullptr;
173
174 void (*copy_construct_)(const void *src, void *dst) = nullptr;
175 void (*copy_construct_n_)(const void *src, void *dst, int64_t n) = nullptr;
176 void (*copy_construct_indices_)(const void *src, void *dst, const IndexMask &mask) = nullptr;
177 void (*copy_construct_compressed_)(const void *src, void *dst, const IndexMask &mask) = nullptr;
178
179 void (*move_assign_)(void *src, void *dst) = nullptr;
180 void (*move_assign_n_)(void *src, void *dst, int64_t n) = nullptr;
181 void (*move_assign_indices_)(void *src, void *dst, const IndexMask &mask) = nullptr;
182
183 void (*move_construct_)(void *src, void *dst) = nullptr;
184 void (*move_construct_n_)(void *src, void *dst, int64_t n) = nullptr;
185 void (*move_construct_indices_)(void *src, void *dst, const IndexMask &mask) = nullptr;
186
187 void (*relocate_assign_)(void *src, void *dst) = nullptr;
188 void (*relocate_assign_n_)(void *src, void *dst, int64_t n) = nullptr;
189 void (*relocate_assign_indices_)(void *src, void *dst, const IndexMask &mask) = nullptr;
190
191 void (*relocate_construct_)(void *src, void *dst) = nullptr;
192 void (*relocate_construct_n_)(void *src, void *dst, int64_t n) = nullptr;
193 void (*relocate_construct_indices_)(void *src, void *dst, const IndexMask &mask) = nullptr;
194
195 void (*fill_assign_n_)(const void *value, void *dst, int64_t n) = nullptr;
196 void (*fill_assign_indices_)(const void *value, void *dst, const IndexMask &mask) = nullptr;
197
198 void (*fill_construct_n_)(const void *value, void *dst, int64_t n) = nullptr;
199 void (*fill_construct_indices_)(const void *value, void *dst, const IndexMask &mask) = nullptr;
200
201 void (*print_)(const void *value, std::stringstream &ss) = nullptr;
202 bool (*is_equal_)(const void *a, const void *b) = nullptr;
203 uint64_t (*hash_)(const void *value) = nullptr;
204
205 const void *default_value_ = nullptr;
206 std::string debug_name_;
207
208 public:
209 template<typename T, CPPTypeFlags Flags>
210 CPPType(TypeTag<T> /*type*/, TypeForValue<CPPTypeFlags, Flags> /*flags*/, StringRef debug_name);
211 virtual ~CPPType() = default;
212
218 template<typename T> static const CPPType &get();
219 template<typename T> static const CPPType &get_impl();
220
225 StringRefNull name() const;
226
227 bool is_printable() const;
228 bool is_equality_comparable() const;
229 bool is_hashable() const;
230
234 bool pointer_has_valid_alignment(const void *ptr) const;
235 bool pointer_can_point_to_instance(const void *ptr) const;
236
245 void default_construct(void *ptr) const;
246 void default_construct_n(void *ptr, int64_t n) const;
247 void default_construct_indices(void *ptr, const IndexMask &mask) const;
248
255 void value_initialize(void *ptr) const;
256 void value_initialize_n(void *ptr, int64_t n) const;
257 void value_initialize_indices(void *ptr, const IndexMask &mask) const;
258
267 void destruct(void *ptr) const;
268 void destruct_n(void *ptr, int64_t n) const;
269 void destruct_indices(void *ptr, const IndexMask &mask) const;
270
277 void copy_assign(const void *src, void *dst) const;
278 void copy_assign_n(const void *src, void *dst, int64_t n) const;
279 void copy_assign_indices(const void *src, void *dst, const IndexMask &mask) const;
280
284 void copy_assign_compressed(const void *src, void *dst, const IndexMask &mask) const;
285
294 void copy_construct(const void *src, void *dst) const;
295 void copy_construct_n(const void *src, void *dst, int64_t n) const;
296 void copy_construct_indices(const void *src, void *dst, const IndexMask &mask) const;
297
301 void copy_construct_compressed(const void *src, void *dst, const IndexMask &mask) const;
302
311 void move_assign(void *src, void *dst) const;
312 void move_assign_n(void *src, void *dst, int64_t n) const;
313 void move_assign_indices(void *src, void *dst, const IndexMask &mask) const;
314
323 void move_construct(void *src, void *dst) const;
324 void move_construct_n(void *src, void *dst, int64_t n) const;
325 void move_construct_indices(void *src, void *dst, const IndexMask &mask) const;
326
335 void relocate_assign(void *src, void *dst) const;
336 void relocate_assign_n(void *src, void *dst, int64_t n) const;
337 void relocate_assign_indices(void *src, void *dst, const IndexMask &mask) const;
338
347 void relocate_construct(void *src, void *dst) const;
348 void relocate_construct_n(void *src, void *dst, int64_t n) const;
349 void relocate_construct_indices(void *src, void *dst, const IndexMask &mask) const;
350
356 void fill_assign_n(const void *value, void *dst, int64_t n) const;
357 void fill_assign_indices(const void *value, void *dst, const IndexMask &mask) const;
358
364 void fill_construct_n(const void *value, void *dst, int64_t n) const;
365 void fill_construct_indices(const void *value, void *dst, const IndexMask &mask) const;
366
367 bool can_exist_in_buffer(const int64_t buffer_size, const int64_t buffer_alignment) const;
368
369 void print(const void *value, std::stringstream &ss) const;
370 std::string to_string(const void *value) const;
371 void print_or_default(const void *value, std::stringstream &ss, StringRef default_value) const;
372
373 bool is_equal(const void *a, const void *b) const;
374 bool is_equal_or_false(const void *a, const void *b) const;
375
376 uint64_t hash(const void *value) const;
377 uint64_t hash_or_fallback(const void *value, uint64_t fallback_hash) const;
378
383 const void *default_value() const;
384
385 uint64_t hash() const;
386
387 void (*destruct_fn() const)(void *);
388
389 template<typename T> bool is() const;
390
391 template<typename... T> bool is_any() const;
392
403 template<typename... Types, typename Fn> void to_static_type(const Fn &fn) const;
404
405 private:
406 template<typename Fn> struct TypeTagExecutor {
407 const Fn &fn;
408
409 template<typename T> void operator()() const
410 {
411 fn(TypeTag<T>{});
412 }
413
414 void operator()() const
415 {
416 fn(TypeTag<void>{});
417 }
418 };
419
420 public:
428 template<typename... Types, typename Fn> void to_static_type_tag(const Fn &fn) const
429 {
430 TypeTagExecutor<Fn> executor{fn};
431 this->to_static_type<Types...>(executor);
432 }
433};
434
439
440} // namespace blender
441
442/* Utility for allocating an uninitialized buffer for a single value of the given #CPPType. */
443#define BUFFER_FOR_CPP_TYPE_VALUE(type, variable_name) \
444 blender::DynamicStackBuffer<64, 64> stack_buffer_for_##variable_name((type).size, \
445 (type).alignment); \
446 void *variable_name = stack_buffer_for_##variable_name.buffer();
447
448namespace blender {
449
450/* Give a compile error instead of a link error when type information is missing. */
451template<> const CPPType &CPPType::get_impl<void>() = delete;
452
457inline bool operator==(const CPPType &a, const CPPType &b)
458{
459 return &a == &b;
460}
461
462inline bool operator!=(const CPPType &a, const CPPType &b)
463{
464 return !(&a == &b);
465}
466
467template<typename T> inline const CPPType &CPPType::get()
468{
469 /* Store the #CPPType locally to avoid making the function call in most cases. */
470 static const CPPType &type = CPPType::get_impl<std::decay_t<T>>();
471 return type;
472}
473
475{
476 return debug_name_;
477}
478
479inline bool CPPType::is_printable() const
480{
481 return print_ != nullptr;
482}
483
485{
486 return is_equal_ != nullptr;
487}
488
489inline bool CPPType::is_hashable() const
490{
491 return hash_ != nullptr;
492}
493
494inline bool CPPType::pointer_has_valid_alignment(const void *ptr) const
495{
496 return (uintptr_t(ptr) & alignment_mask_) == 0;
497}
498
499inline bool CPPType::pointer_can_point_to_instance(const void *ptr) const
500{
501 return ptr != nullptr && pointer_has_valid_alignment(ptr);
502}
503
504inline void CPPType::default_construct(void *ptr) const
505{
506 default_construct_(ptr);
507}
508
509inline void CPPType::default_construct_n(void *ptr, int64_t n) const
510{
511 default_construct_n_(ptr, n);
512}
513
514inline void CPPType::default_construct_indices(void *ptr, const IndexMask &mask) const
515{
516 default_construct_indices_(ptr, mask);
517}
518
519inline void CPPType::value_initialize(void *ptr) const
520{
521 value_initialize_(ptr);
522}
523
524inline void CPPType::value_initialize_n(void *ptr, int64_t n) const
525{
526 value_initialize_n_(ptr, n);
527}
528
529inline void CPPType::value_initialize_indices(void *ptr, const IndexMask &mask) const
530{
531 value_initialize_indices_(ptr, mask);
532}
533
534inline void CPPType::destruct(void *ptr) const
535{
536 destruct_(ptr);
537}
538
539inline void CPPType::destruct_n(void *ptr, int64_t n) const
540{
541 destruct_n_(ptr, n);
542}
543
544inline void CPPType::destruct_indices(void *ptr, const IndexMask &mask) const
545{
546 destruct_indices_(ptr, mask);
547}
548
549inline void CPPType::copy_assign(const void *src, void *dst) const
550{
551 copy_assign_(src, dst);
552}
553
554inline void CPPType::copy_assign_n(const void *src, void *dst, int64_t n) const
555{
556 copy_assign_n_(src, dst, n);
557}
558
559inline void CPPType::copy_assign_indices(const void *src, void *dst, const IndexMask &mask) const
560{
561 copy_assign_indices_(src, dst, mask);
562}
563
564inline void CPPType::copy_assign_compressed(const void *src,
565 void *dst,
566 const IndexMask &mask) const
567{
568 copy_assign_compressed_(src, dst, mask);
569}
570
571inline void CPPType::copy_construct(const void *src, void *dst) const
572{
573 copy_construct_(src, dst);
574}
575
576inline void CPPType::copy_construct_n(const void *src, void *dst, int64_t n) const
577{
578 copy_construct_n_(src, dst, n);
579}
580
581inline void CPPType::copy_construct_indices(const void *src,
582 void *dst,
583 const IndexMask &mask) const
584{
585 copy_construct_indices_(src, dst, mask);
586}
587
588inline void CPPType::copy_construct_compressed(const void *src,
589 void *dst,
590 const IndexMask &mask) const
591{
592 copy_construct_compressed_(src, dst, mask);
593}
594
595inline void CPPType::move_assign(void *src, void *dst) const
596{
597 move_assign_(src, dst);
598}
599
600inline void CPPType::move_assign_n(void *src, void *dst, int64_t n) const
601{
602 move_assign_n_(src, dst, n);
603}
604
605inline void CPPType::move_assign_indices(void *src, void *dst, const IndexMask &mask) const
606{
607 move_assign_indices_(src, dst, mask);
608}
609
610inline void CPPType::move_construct(void *src, void *dst) const
611{
612 move_construct_(src, dst);
613}
614
615inline void CPPType::move_construct_n(void *src, void *dst, int64_t n) const
616{
617 move_construct_n_(src, dst, n);
618}
619
620inline void CPPType::move_construct_indices(void *src, void *dst, const IndexMask &mask) const
621{
622 move_construct_indices_(src, dst, mask);
623}
624
625inline void CPPType::relocate_assign(void *src, void *dst) const
626{
627 relocate_assign_(src, dst);
628}
629
630inline void CPPType::relocate_assign_n(void *src, void *dst, int64_t n) const
631{
632 relocate_assign_n_(src, dst, n);
633}
634
635inline void CPPType::relocate_assign_indices(void *src, void *dst, const IndexMask &mask) const
636{
637 relocate_assign_indices_(src, dst, mask);
638}
639
640inline void CPPType::relocate_construct(void *src, void *dst) const
641{
642 relocate_construct_(src, dst);
643}
644
645inline void CPPType::relocate_construct_n(void *src, void *dst, int64_t n) const
646{
647 relocate_construct_n_(src, dst, n);
648}
649
650inline void CPPType::relocate_construct_indices(void *src, void *dst, const IndexMask &mask) const
651{
652 relocate_construct_indices_(src, dst, mask);
653}
654
655inline void CPPType::fill_assign_n(const void *value, void *dst, int64_t n) const
656{
657 fill_assign_n_(value, dst, n);
658}
659
660inline void CPPType::fill_assign_indices(const void *value, void *dst, const IndexMask &mask) const
661{
662 fill_assign_indices_(value, dst, mask);
663}
664
665inline void CPPType::fill_construct_n(const void *value, void *dst, int64_t n) const
666{
667 fill_construct_n_(value, dst, n);
668}
669
670inline void CPPType::fill_construct_indices(const void *value,
671 void *dst,
672 const IndexMask &mask) const
673{
674 fill_construct_indices_(value, dst, mask);
675}
676
677inline bool CPPType::can_exist_in_buffer(const int64_t buffer_size,
678 const int64_t buffer_alignment) const
679{
680 return this->size <= buffer_size && this->alignment <= buffer_alignment;
681}
682
683inline void CPPType::print(const void *value, std::stringstream &ss) const
684{
686 print_(value, ss);
687}
688
689inline bool CPPType::is_equal(const void *a, const void *b) const
690{
691 return is_equal_(a, b);
692}
693
694inline bool CPPType::is_equal_or_false(const void *a, const void *b) const
695{
696 if (this->is_equality_comparable()) {
697 return this->is_equal(a, b);
698 }
699 return false;
700}
701
702inline uint64_t CPPType::hash(const void *value) const
703{
704 return hash_(value);
705}
706
707inline uint64_t CPPType::hash_or_fallback(const void *value, uint64_t fallback_hash) const
708{
709 if (this->is_hashable()) {
710 return this->hash(value);
711 }
712 return fallback_hash;
713}
714
715inline const void *CPPType::default_value() const
716{
717 return default_value_;
718}
719
721{
722 return get_default_hash(this);
723}
724
725inline void (*CPPType::destruct_fn() const)(void *)
726{
727 return destruct_;
728}
729
730template<typename T> inline bool CPPType::is() const
731{
732 return this == &CPPType::get<std::decay_t<T>>();
733}
734
735template<typename... T> inline bool CPPType::is_any() const
736{
737 return (this->is<T>() || ...);
738}
739
740template<typename... Types, typename Fn> inline void CPPType::to_static_type(const Fn &fn) const
741{
742 using Callback = void (*)(const Fn &fn);
743
744 /* Build a lookup table to avoid having to compare the current #CPPType with every type in
745 * #Types one after another. */
746 static const Map<const CPPType *, Callback> callback_map = []() {
748 /* This adds an entry in the map for every type in #Types. */
749 (callback_map.add_new(&CPPType::get<Types>(),
750 [](const Fn &fn) {
751 /* Call the templated `operator()` of the given function object. */
752 fn.template operator()<Types>();
753 }),
754 ...);
755 return callback_map;
756 }();
757
758 const Callback callback = callback_map.lookup_default(this, nullptr);
759 if (callback != nullptr) {
760 callback(fn);
761 }
762 else {
763 /* Call the non-templated `operator()` of the given function object. */
764 fn();
765 }
766}
767
768} // namespace blender
#define BLI_assert(a)
Definition BLI_assert.h:46
CPPTypeFlags
#define ENUM_OPERATORS(_type, _max)
long long int int64_t
unsigned long long int uint64_t
SIMD_FORCE_INLINE btVector3 operator()(const btVector3 &x) const
Return the transform of the vector.
Definition btTransform.h:90
void(*)(void *) destruct_fn() const
void copy_construct_n(const void *src, void *dst, int64_t n) const
void(*)(void *) destruct_fn() const
bool is_any() const
static const CPPType & get()
void value_initialize_indices(void *ptr, const IndexMask &mask) const
void to_static_type(const Fn &fn) const
void default_construct_n(void *ptr, int64_t n) const
virtual ~CPPType()=default
void destruct_n(void *ptr, int64_t n) const
void copy_assign_indices(const void *src, void *dst, const IndexMask &mask) const
void move_construct_n(void *src, void *dst, int64_t n) 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 fill_construct_indices(const void *value, void *dst, const IndexMask &mask) const
void relocate_assign_n(void *src, void *dst, int64_t n) const
uint64_t hash() const
void copy_construct_indices(const void *src, void *dst, const IndexMask &mask) const
void fill_assign_indices(const void *value, void *dst, const IndexMask &mask) const
void move_assign(void *src, void *dst) const
bool is_printable() const
std::string to_string(const void *value) const
Definition cpp_type.cc:15
void move_assign_indices(void *src, void *dst, const IndexMask &mask) const
void fill_construct_n(const void *value, void *dst, int64_t n) 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
StringRefNull name() const
static const CPPType & get_impl()
void relocate_assign_indices(void *src, void *dst, const IndexMask &mask) const
bool is() const
void copy_construct_compressed(const void *src, void *dst, const IndexMask &mask) 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
bool has_special_member_functions
void destruct_indices(void *ptr, const IndexMask &mask) const
void copy_construct(const void *src, void *dst) const
void destruct(void *ptr) const
bool pointer_has_valid_alignment(const void *ptr) const
void default_construct_indices(void *ptr, const IndexMask &mask) const
void print_or_default(const void *value, std::stringstream &ss, StringRef default_value) const
Definition cpp_type.cc:22
void copy_assign(const void *src, void *dst) const
void to_static_type_tag(const Fn &fn) const
const void * default_value() 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 print(const void *value, std::stringstream &ss) const
bool pointer_can_point_to_instance(const void *ptr) const
void relocate_construct_n(void *src, void *dst, int64_t n) const
CPPType(TypeTag< T >, TypeForValue< CPPTypeFlags, Flags >, StringRef debug_name)
void relocate_assign(void *src, void *dst) const
void default_construct(void *ptr) const
void relocate_construct_indices(void *src, void *dst, const IndexMask &mask) const
void copy_assign_compressed(const void *src, void *dst, const IndexMask &mask) const
void move_construct_indices(void *src, void *dst, const IndexMask &mask) const
void value_initialize(void *ptr) const
Value lookup_default(const Key &key, const Value &default_value) const
Definition BLI_map.hh:570
void add_new(const Key &key, const Value &value)
Definition BLI_map.hh:265
NonCopyable(const NonCopyable &other)=delete
NonMovable(NonMovable &&other)=delete
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
#define T
bool operator!=(const CPPType &a, const CPPType &b)
uint64_t get_default_hash(const T &v, const Args &...args)
Definition BLI_hash.hh:233
void register_cpp_types()
bool operator==(const CPPType &a, const CPPType &b)
PointerRNA * ptr
Definition wm_files.cc:4238