Blender V4.3
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
75#include "BLI_hash.hh"
76#include "BLI_index_mask.hh"
77#include "BLI_map.hh"
78#include "BLI_math_base.h"
80#include "BLI_string_ref.hh"
81#include "BLI_utility_mixins.hh"
82
88enum class CPPTypeFlags {
89 None = 0,
90 Hashable = 1 << 0,
91 Printable = 1 << 1,
92 EqualityComparable = 1 << 2,
93 IdentityDefaultValue = 1 << 3,
94
96};
98
99namespace blender {
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, const IndexMask &mask) = nullptr;
112
113 void (*value_initialize_)(void *ptr) = nullptr;
114 void (*value_initialize_indices_)(void *ptr, const IndexMask &mask) = nullptr;
115
116 void (*destruct_)(void *ptr) = nullptr;
117 void (*destruct_indices_)(void *ptr, const IndexMask &mask) = nullptr;
118
119 void (*copy_assign_)(const void *src, void *dst) = nullptr;
120 void (*copy_assign_indices_)(const void *src, void *dst, const IndexMask &mask) = nullptr;
121 void (*copy_assign_compressed_)(const void *src, void *dst, const IndexMask &mask) = nullptr;
122
123 void (*copy_construct_)(const void *src, void *dst) = nullptr;
124 void (*copy_construct_indices_)(const void *src, void *dst, const IndexMask &mask) = nullptr;
125 void (*copy_construct_compressed_)(const void *src, void *dst, const IndexMask &mask) = nullptr;
126
127 void (*move_assign_)(void *src, void *dst) = nullptr;
128 void (*move_assign_indices_)(void *src, void *dst, const IndexMask &mask) = nullptr;
129
130 void (*move_construct_)(void *src, void *dst) = nullptr;
131 void (*move_construct_indices_)(void *src, void *dst, const IndexMask &mask) = nullptr;
132
133 void (*relocate_assign_)(void *src, void *dst) = nullptr;
134 void (*relocate_assign_indices_)(void *src, void *dst, const IndexMask &mask) = nullptr;
135
136 void (*relocate_construct_)(void *src, void *dst) = nullptr;
137 void (*relocate_construct_indices_)(void *src, void *dst, const IndexMask &mask) = nullptr;
138
139 void (*fill_assign_indices_)(const void *value, void *dst, const IndexMask &mask) = nullptr;
140
141 void (*fill_construct_indices_)(const void *value, void *dst, const 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>
152 CPPType(TypeTag<T> /*type*/, TypeForValue<CPPTypeFlags, Flags> /*flags*/, StringRef debug_name);
153 virtual ~CPPType() = default;
154
159 friend bool operator==(const CPPType &a, const CPPType &b)
160 {
161 return &a == &b;
162 }
163
164 friend bool operator!=(const CPPType &a, const CPPType &b)
165 {
166 return !(&a == &b);
167 }
168
174 template<typename T> static const CPPType &get()
175 {
176 /* Store the #CPPType locally to avoid making the function call in most cases. */
177 static const CPPType &type = CPPType::get_impl<std::decay_t<T>>();
178 return type;
179 }
180 template<typename T> static const CPPType &get_impl();
181
187 {
188 return debug_name_;
189 }
190
197 int64_t size() const
198 {
199 return size_;
200 }
201
209 {
210 return alignment_;
211 }
212
221 {
222 return is_trivially_destructible_;
223 }
224
232 bool is_trivial() const
233 {
234 return is_trivial_;
235 }
236
238 {
239 return default_construct_ != nullptr;
240 }
241
243 {
244 return copy_assign_ != nullptr;
245 }
246
248 {
249 return move_assign_ != nullptr;
250 }
251
252 bool is_destructible() const
253 {
254 return destruct_ != nullptr;
255 }
256
258 {
259 return copy_assign_ != nullptr;
260 }
261
263 {
264 return copy_construct_ != nullptr;
265 }
266
267 bool is_printable() const
268 {
269 return print_ != nullptr;
270 }
271
273 {
274 return is_equal_ != nullptr;
275 }
276
277 bool is_hashable() const
278 {
279 return hash_ != nullptr;
280 }
281
292 {
293 return has_special_member_functions_;
294 }
295
299 bool pointer_has_valid_alignment(const void *ptr) const
300 {
301 return (uintptr_t(ptr) & alignment_mask_) == 0;
302 }
303
304 bool pointer_can_point_to_instance(const void *ptr) const
305 {
306 return ptr != nullptr && pointer_has_valid_alignment(ptr);
307 }
308
317 void default_construct(void *ptr) const
318 {
320
321 default_construct_(ptr);
322 }
323
324 void default_construct_n(void *ptr, int64_t n) const
325 {
327 }
328
329 void default_construct_indices(void *ptr, const IndexMask &mask) const
330 {
331 BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(ptr));
332
333 default_construct_indices_(ptr, mask);
334 }
335
342 void value_initialize(void *ptr) const
343 {
345
346 value_initialize_(ptr);
347 }
348
349 void value_initialize_n(void *ptr, int64_t n) const
350 {
351 this->value_initialize_indices(ptr, IndexMask(n));
352 }
353
354 void value_initialize_indices(void *ptr, const IndexMask &mask) const
355 {
356 BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(ptr));
357
358 value_initialize_indices_(ptr, mask);
359 }
360
369 void destruct(void *ptr) const
370 {
372
373 destruct_(ptr);
374 }
375
376 void destruct_n(void *ptr, int64_t n) const
377 {
378 this->destruct_indices(ptr, IndexMask(n));
379 }
380
381 void destruct_indices(void *ptr, const IndexMask &mask) const
382 {
383 BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(ptr));
384
385 destruct_indices_(ptr, mask);
386 }
387
394 void copy_assign(const void *src, void *dst) const
395 {
398
399 copy_assign_(src, dst);
400 }
401
402 void copy_assign_n(const void *src, void *dst, int64_t n) const
403 {
404 this->copy_assign_indices(src, dst, IndexMask(n));
405 }
406
407 void copy_assign_indices(const void *src, void *dst, const IndexMask &mask) const
408 {
409 BLI_assert(mask.size() == 0 || src != dst);
410 BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(src));
411 BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(dst));
412
413 copy_assign_indices_(src, dst, mask);
414 }
415
419 void copy_assign_compressed(const void *src, void *dst, const IndexMask &mask) const
420 {
421 BLI_assert(mask.size() == 0 || src != dst);
422 BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(src));
423 BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(dst));
424
425 copy_assign_compressed_(src, dst, mask);
426 }
427
436 void copy_construct(const void *src, void *dst) const
437 {
438 BLI_assert(src != dst || is_trivial_);
441
442 copy_construct_(src, dst);
443 }
444
445 void copy_construct_n(const void *src, void *dst, int64_t n) const
446 {
447 this->copy_construct_indices(src, dst, IndexMask(n));
448 }
449
450 void copy_construct_indices(const void *src, void *dst, const IndexMask &mask) const
451 {
452 BLI_assert(mask.size() == 0 || src != dst);
453 BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(src));
454 BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(dst));
455
456 copy_construct_indices_(src, dst, mask);
457 }
458
462 void copy_construct_compressed(const void *src, void *dst, const IndexMask &mask) const
463 {
464 BLI_assert(mask.size() == 0 || src != dst);
465 BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(src));
466 BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(dst));
467
468 copy_construct_compressed_(src, dst, mask);
469 }
470
479 void move_assign(void *src, void *dst) const
480 {
483
484 move_assign_(src, dst);
485 }
486
487 void move_assign_n(void *src, void *dst, int64_t n) const
488 {
489 this->move_assign_indices(src, dst, IndexMask(n));
490 }
491
492 void move_assign_indices(void *src, void *dst, const IndexMask &mask) const
493 {
494 BLI_assert(mask.size() == 0 || src != dst);
495 BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(src));
496 BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(dst));
497
498 move_assign_indices_(src, dst, mask);
499 }
500
509 void move_construct(void *src, void *dst) const
510 {
511 BLI_assert(src != dst || is_trivial_);
514
515 move_construct_(src, dst);
516 }
517
518 void move_construct_n(void *src, void *dst, int64_t n) const
519 {
520 this->move_construct_indices(src, dst, IndexMask(n));
521 }
522
523 void move_construct_indices(void *src, void *dst, const IndexMask &mask) const
524 {
525 BLI_assert(mask.size() == 0 || src != dst);
526 BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(src));
527 BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(dst));
528
529 move_construct_indices_(src, dst, mask);
530 }
531
540 void relocate_assign(void *src, void *dst) const
541 {
542 BLI_assert(src != dst || is_trivial_);
545
546 relocate_assign_(src, dst);
547 }
548
549 void relocate_assign_n(void *src, void *dst, int64_t n) const
550 {
551 this->relocate_assign_indices(src, dst, IndexMask(n));
552 }
553
554 void relocate_assign_indices(void *src, void *dst, const IndexMask &mask) const
555 {
556 BLI_assert(mask.size() == 0 || src != dst);
557 BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(src));
558 BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(dst));
559
560 relocate_assign_indices_(src, dst, mask);
561 }
562
571 void relocate_construct(void *src, void *dst) const
572 {
573 BLI_assert(src != dst || is_trivial_);
576
577 relocate_construct_(src, dst);
578 }
579
580 void relocate_construct_n(void *src, void *dst, int64_t n) const
581 {
582 this->relocate_construct_indices(src, dst, IndexMask(n));
583 }
584
585 void relocate_construct_indices(void *src, void *dst, const IndexMask &mask) const
586 {
587 BLI_assert(mask.size() == 0 || src != dst);
588 BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(src));
589 BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(dst));
590
591 relocate_construct_indices_(src, dst, mask);
592 }
593
599 void fill_assign_n(const void *value, void *dst, int64_t n) const
600 {
601 this->fill_assign_indices(value, dst, IndexMask(n));
602 }
603
604 void fill_assign_indices(const void *value, void *dst, const IndexMask &mask) const
605 {
606 BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(value));
607 BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(dst));
608
609 fill_assign_indices_(value, dst, mask);
610 }
611
617 void fill_construct_n(const void *value, void *dst, int64_t n) const
618 {
619 this->fill_construct_indices(value, dst, IndexMask(n));
620 }
621
622 void fill_construct_indices(const void *value, void *dst, const IndexMask &mask) const
623 {
624 BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(value));
625 BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(dst));
626
627 fill_construct_indices_(value, dst, mask);
628 }
629
630 bool can_exist_in_buffer(const int64_t buffer_size, const int64_t buffer_alignment) const
631 {
632 return size_ <= buffer_size && alignment_ <= buffer_alignment;
633 }
634
635 void print(const void *value, std::stringstream &ss) const
636 {
638 print_(value, ss);
639 }
640
641 std::string to_string(const void *value) const;
642
643 void print_or_default(const void *value, std::stringstream &ss, StringRef default_value) const;
644
645 bool is_equal(const void *a, const void *b) const
646 {
649 return is_equal_(a, b);
650 }
651
652 bool is_equal_or_false(const void *a, const void *b) const
653 {
654 if (this->is_equality_comparable()) {
655 return this->is_equal(a, b);
656 }
657 return false;
658 }
659
660 uint64_t hash(const void *value) const
661 {
663 return hash_(value);
664 }
665
666 uint64_t hash_or_fallback(const void *value, uint64_t fallback_hash) const
667 {
668 if (this->is_hashable()) {
669 return this->hash(value);
670 }
671 return fallback_hash;
672 }
673
678 const void *default_value() const
679 {
680 return default_value_;
681 }
682
684 {
685 return get_default_hash(this);
686 }
687
688 void (*destruct_fn() const)(void *)
689 {
690 return destruct_;
691 }
692
693 template<typename T> bool is() const
694 {
695 return this == &CPPType::get<std::decay_t<T>>();
696 }
697
698 template<typename... T> bool is_any() const
699 {
700 return (this->is<T>() || ...);
701 }
702
713 template<typename... Types, typename Fn> void to_static_type(const Fn &fn) const
714 {
715 using Callback = void (*)(const Fn &fn);
716
717 /* Build a lookup table to avoid having to compare the current #CPPType with every type in
718 * #Types one after another. */
719 static const Map<const CPPType *, Callback> callback_map = []() {
721 /* This adds an entry in the map for every type in #Types. */
722 (callback_map.add_new(&CPPType::get<Types>(),
723 [](const Fn &fn) {
724 /* Call the templated `operator()` of the given function object. */
725 fn.template operator()<Types>();
726 }),
727 ...);
728 return callback_map;
729 }();
730
731 const Callback callback = callback_map.lookup_default(this, nullptr);
732 if (callback != nullptr) {
733 callback(fn);
734 }
735 else {
736 /* Call the non-templated `operator()` of the given function object. */
737 fn();
738 }
739 }
740
741 private:
742 template<typename Fn> struct TypeTagExecutor {
743 const Fn &fn;
744
745 template<typename T> void operator()() const
746 {
747 fn(TypeTag<T>{});
748 }
749
750 void operator()() const
751 {
752 fn(TypeTag<void>{});
753 }
754 };
755
756 public:
764 template<typename... Types, typename Fn> void to_static_type_tag(const Fn &fn) const
765 {
766 TypeTagExecutor<Fn> executor{fn};
767 this->to_static_type<Types...>(executor);
768 }
769};
770
775
776} // namespace blender
777
778/* Utility for allocating an uninitialized buffer for a single value of the given #CPPType. */
779#define BUFFER_FOR_CPP_TYPE_VALUE(type, variable_name) \
780 blender::DynamicStackBuffer<64, 64> stack_buffer_for_##variable_name((type).size(), \
781 (type).alignment()); \
782 void *variable_name = stack_buffer_for_##variable_name.buffer();
#define BLI_assert(a)
Definition BLI_assert.h:50
CPPTypeFlags
#define ENUM_OPERATORS(_type, _max)
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_any() const
bool is_trivial() const
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:11
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_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_impl()
static const CPPType & get()
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
uint64_t hash(const void *value) const
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
bool is_default_constructible() const
int64_t size() const
bool is_copy_assignable() const
int64_t alignment() const
void default_construct_indices(void *ptr, const IndexMask &mask) const
bool is_destructible() const
bool is_move_constructible() const
void print_or_default(const void *value, std::stringstream &ss, StringRef default_value) const
Definition cpp_type.cc:18
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
bool is_trivially_destructible() 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
friend bool operator==(const CPPType &a, const CPPType &b)
void value_initialize(void *ptr) const
Value lookup_default(const Key &key, const Value &default_value) const
Definition BLI_map.hh:531
void add_new(const Key &key, const Value &value)
Definition BLI_map.hh:241
local_group_size(16, 16) .push_constant(Type b
DEGForeachIDComponentCallback callback
ccl_device_inline float4 mask(const int4 mask, const float4 a)
uint64_t get_default_hash(const T &v)
Definition BLI_hash.hh:219
void register_cpp_types()
_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.cc:4126