Blender V4.5
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
454inline bool operator==(const CPPType &a, const CPPType &b)
455{
456 return &a == &b;
457}
458
459inline bool operator!=(const CPPType &a, const CPPType &b)
460{
461 return !(&a == &b);
462}
463
464template<typename T> inline const CPPType &CPPType::get()
465{
466 /* Store the #CPPType locally to avoid making the function call in most cases. */
467 static const CPPType &type = CPPType::get_impl<std::decay_t<T>>();
468 return type;
469}
470
472{
473 return debug_name_;
474}
475
476inline bool CPPType::is_printable() const
477{
478 return print_ != nullptr;
479}
480
482{
483 return is_equal_ != nullptr;
484}
485
486inline bool CPPType::is_hashable() const
487{
488 return hash_ != nullptr;
489}
490
491inline bool CPPType::pointer_has_valid_alignment(const void *ptr) const
492{
493 return (uintptr_t(ptr) & alignment_mask_) == 0;
494}
495
496inline bool CPPType::pointer_can_point_to_instance(const void *ptr) const
497{
498 return ptr != nullptr && pointer_has_valid_alignment(ptr);
499}
500
501inline void CPPType::default_construct(void *ptr) const
502{
503 default_construct_(ptr);
504}
505
506inline void CPPType::default_construct_n(void *ptr, int64_t n) const
507{
508 default_construct_n_(ptr, n);
509}
510
511inline void CPPType::default_construct_indices(void *ptr, const IndexMask &mask) const
512{
513 default_construct_indices_(ptr, mask);
514}
515
516inline void CPPType::value_initialize(void *ptr) const
517{
518 value_initialize_(ptr);
519}
520
521inline void CPPType::value_initialize_n(void *ptr, int64_t n) const
522{
523 value_initialize_n_(ptr, n);
524}
525
526inline void CPPType::value_initialize_indices(void *ptr, const IndexMask &mask) const
527{
528 value_initialize_indices_(ptr, mask);
529}
530
531inline void CPPType::destruct(void *ptr) const
532{
533 destruct_(ptr);
534}
535
536inline void CPPType::destruct_n(void *ptr, int64_t n) const
537{
538 destruct_n_(ptr, n);
539}
540
541inline void CPPType::destruct_indices(void *ptr, const IndexMask &mask) const
542{
543 destruct_indices_(ptr, mask);
544}
545
546inline void CPPType::copy_assign(const void *src, void *dst) const
547{
548 copy_assign_(src, dst);
549}
550
551inline void CPPType::copy_assign_n(const void *src, void *dst, int64_t n) const
552{
553 copy_assign_n_(src, dst, n);
554}
555
556inline void CPPType::copy_assign_indices(const void *src, void *dst, const IndexMask &mask) const
557{
558 copy_assign_indices_(src, dst, mask);
559}
560
561inline void CPPType::copy_assign_compressed(const void *src,
562 void *dst,
563 const IndexMask &mask) const
564{
565 copy_assign_compressed_(src, dst, mask);
566}
567
568inline void CPPType::copy_construct(const void *src, void *dst) const
569{
570 copy_construct_(src, dst);
571}
572
573inline void CPPType::copy_construct_n(const void *src, void *dst, int64_t n) const
574{
575 copy_construct_n_(src, dst, n);
576}
577
578inline void CPPType::copy_construct_indices(const void *src,
579 void *dst,
580 const IndexMask &mask) const
581{
582 copy_construct_indices_(src, dst, mask);
583}
584
585inline void CPPType::copy_construct_compressed(const void *src,
586 void *dst,
587 const IndexMask &mask) const
588{
589 copy_construct_compressed_(src, dst, mask);
590}
591
592inline void CPPType::move_assign(void *src, void *dst) const
593{
594 move_assign_(src, dst);
595}
596
597inline void CPPType::move_assign_n(void *src, void *dst, int64_t n) const
598{
599 move_assign_n_(src, dst, n);
600}
601
602inline void CPPType::move_assign_indices(void *src, void *dst, const IndexMask &mask) const
603{
604 move_assign_indices_(src, dst, mask);
605}
606
607inline void CPPType::move_construct(void *src, void *dst) const
608{
609 move_construct_(src, dst);
610}
611
612inline void CPPType::move_construct_n(void *src, void *dst, int64_t n) const
613{
614 move_construct_n_(src, dst, n);
615}
616
617inline void CPPType::move_construct_indices(void *src, void *dst, const IndexMask &mask) const
618{
619 move_construct_indices_(src, dst, mask);
620}
621
622inline void CPPType::relocate_assign(void *src, void *dst) const
623{
624 relocate_assign_(src, dst);
625}
626
627inline void CPPType::relocate_assign_n(void *src, void *dst, int64_t n) const
628{
629 relocate_assign_n_(src, dst, n);
630}
631
632inline void CPPType::relocate_assign_indices(void *src, void *dst, const IndexMask &mask) const
633{
634 relocate_assign_indices_(src, dst, mask);
635}
636
637inline void CPPType::relocate_construct(void *src, void *dst) const
638{
639 relocate_construct_(src, dst);
640}
641
642inline void CPPType::relocate_construct_n(void *src, void *dst, int64_t n) const
643{
644 relocate_construct_n_(src, dst, n);
645}
646
647inline void CPPType::relocate_construct_indices(void *src, void *dst, const IndexMask &mask) const
648{
649 relocate_construct_indices_(src, dst, mask);
650}
651
652inline void CPPType::fill_assign_n(const void *value, void *dst, int64_t n) const
653{
654 fill_assign_n_(value, dst, n);
655}
656
657inline void CPPType::fill_assign_indices(const void *value, void *dst, const IndexMask &mask) const
658{
659 fill_assign_indices_(value, dst, mask);
660}
661
662inline void CPPType::fill_construct_n(const void *value, void *dst, int64_t n) const
663{
664 fill_construct_n_(value, dst, n);
665}
666
667inline void CPPType::fill_construct_indices(const void *value,
668 void *dst,
669 const IndexMask &mask) const
670{
671 fill_construct_indices_(value, dst, mask);
672}
673
674inline bool CPPType::can_exist_in_buffer(const int64_t buffer_size,
675 const int64_t buffer_alignment) const
676{
677 return this->size <= buffer_size && this->alignment <= buffer_alignment;
678}
679
680inline void CPPType::print(const void *value, std::stringstream &ss) const
681{
683 print_(value, ss);
684}
685
686inline bool CPPType::is_equal(const void *a, const void *b) const
687{
688 return is_equal_(a, b);
689}
690
691inline bool CPPType::is_equal_or_false(const void *a, const void *b) const
692{
693 if (this->is_equality_comparable()) {
694 return this->is_equal(a, b);
695 }
696 return false;
697}
698
699inline uint64_t CPPType::hash(const void *value) const
700{
701 return hash_(value);
702}
703
704inline uint64_t CPPType::hash_or_fallback(const void *value, uint64_t fallback_hash) const
705{
706 if (this->is_hashable()) {
707 return this->hash(value);
708 }
709 return fallback_hash;
710}
711
712inline const void *CPPType::default_value() const
713{
714 return default_value_;
715}
716
718{
719 return get_default_hash(this);
720}
721
722inline void (*CPPType::destruct_fn() const)(void *)
723{
724 return destruct_;
725}
726
727template<typename T> inline bool CPPType::is() const
728{
729 return this == &CPPType::get<std::decay_t<T>>();
730}
731
732template<typename... T> inline bool CPPType::is_any() const
733{
734 return (this->is<T>() || ...);
735}
736
737template<typename... Types, typename Fn> inline void CPPType::to_static_type(const Fn &fn) const
738{
739 using Callback = void (*)(const Fn &fn);
740
741 /* Build a lookup table to avoid having to compare the current #CPPType with every type in
742 * #Types one after another. */
743 static const Map<const CPPType *, Callback> callback_map = []() {
745 /* This adds an entry in the map for every type in #Types. */
746 (callback_map.add_new(&CPPType::get<Types>(),
747 [](const Fn &fn) {
748 /* Call the templated `operator()` of the given function object. */
749 fn.template operator()<Types>();
750 }),
751 ...);
752 return callback_map;
753 }();
754
755 const Callback callback = callback_map.lookup_default(this, nullptr);
756 if (callback != nullptr) {
757 callback(fn);
758 }
759 else {
760 /* Call the non-templated `operator()` of the given function object. */
761 fn();
762 }
763}
764
765} // 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:4226