From 7d281a4f7d354d270fc9c9f3c7a65b4409362aa0 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Mon, 28 Jun 2021 13:13:52 +0200 Subject: Functions: improve CPPType * Reduce code duplication. * Give methods more standardized names (e.g. `move_to_initialized` -> `move_assign`). * Support wrapping arbitrary C++ types, even those that e.g. are not copyable. --- source/blender/functions/FN_cpp_type_make.hh | 201 +++++++++++++-------------- 1 file changed, 99 insertions(+), 102 deletions(-) (limited to 'source/blender/functions/FN_cpp_type_make.hh') diff --git a/source/blender/functions/FN_cpp_type_make.hh b/source/blender/functions/FN_cpp_type_make.hh index cd14fe8c078..529ec261946 100644 --- a/source/blender/functions/FN_cpp_type_make.hh +++ b/source/blender/functions/FN_cpp_type_make.hh @@ -20,19 +20,16 @@ * \ingroup fn */ +#include "BLI_utildefines.h" #include "FN_cpp_type.hh" namespace blender::fn::cpp_type_util { -template void construct_default_cb(void *ptr) +template void default_construct_cb(void *ptr) { new (ptr) T; } -template void construct_default_n_cb(void *ptr, int64_t n) -{ - blender::default_construct_n(static_cast(ptr), n); -} -template void construct_default_indices_cb(void *ptr, IndexMask mask) +template void default_construct_indices_cb(void *ptr, IndexMask mask) { mask.foreach_index([&](int64_t i) { new (static_cast(ptr) + i) T; }); } @@ -41,31 +38,17 @@ template void destruct_cb(void *ptr) { (static_cast(ptr))->~T(); } -template void destruct_n_cb(void *ptr, int64_t n) -{ - blender::destruct_n(static_cast(ptr), n); -} template void destruct_indices_cb(void *ptr, IndexMask mask) { T *ptr_ = static_cast(ptr); mask.foreach_index([&](int64_t i) { ptr_[i].~T(); }); } -template void copy_to_initialized_cb(const void *src, void *dst) +template void copy_assign_cb(const void *src, void *dst) { *static_cast(dst) = *static_cast(src); } -template void copy_to_initialized_n_cb(const void *src, void *dst, int64_t n) -{ - const T *src_ = static_cast(src); - T *dst_ = static_cast(dst); - - for (int64_t i = 0; i < n; i++) { - dst_[i] = src_[i]; - } -} -template -void copy_to_initialized_indices_cb(const void *src, void *dst, IndexMask mask) +template void copy_assign_indices_cb(const void *src, void *dst, IndexMask mask) { const T *src_ = static_cast(src); T *dst_ = static_cast(dst); @@ -73,16 +56,11 @@ void copy_to_initialized_indices_cb(const void *src, void *dst, IndexMask mask) mask.foreach_index([&](int64_t i) { dst_[i] = src_[i]; }); } -template void copy_to_uninitialized_cb(const void *src, void *dst) +template void copy_construct_cb(const void *src, void *dst) { blender::uninitialized_copy_n(static_cast(src), 1, static_cast(dst)); } -template void copy_to_uninitialized_n_cb(const void *src, void *dst, int64_t n) -{ - blender::uninitialized_copy_n(static_cast(src), n, static_cast(dst)); -} -template -void copy_to_uninitialized_indices_cb(const void *src, void *dst, IndexMask mask) +template void copy_construct_indices_cb(const void *src, void *dst, IndexMask mask) { const T *src_ = static_cast(src); T *dst_ = static_cast(dst); @@ -90,15 +68,11 @@ void copy_to_uninitialized_indices_cb(const void *src, void *dst, IndexMask mask mask.foreach_index([&](int64_t i) { new (dst_ + i) T(src_[i]); }); } -template void move_to_initialized_cb(void *src, void *dst) +template void move_assign_cb(void *src, void *dst) { blender::initialized_move_n(static_cast(src), 1, static_cast(dst)); } -template void move_to_initialized_n_cb(void *src, void *dst, int64_t n) -{ - blender::initialized_move_n(static_cast(src), n, static_cast(dst)); -} -template void move_to_initialized_indices_cb(void *src, void *dst, IndexMask mask) +template void move_assign_indices_cb(void *src, void *dst, IndexMask mask) { T *src_ = static_cast(src); T *dst_ = static_cast(dst); @@ -106,15 +80,11 @@ template void move_to_initialized_indices_cb(void *src, void *dst, I mask.foreach_index([&](int64_t i) { dst_[i] = std::move(src_[i]); }); } -template void move_to_uninitialized_cb(void *src, void *dst) +template void move_construct_cb(void *src, void *dst) { blender::uninitialized_move_n(static_cast(src), 1, static_cast(dst)); } -template void move_to_uninitialized_n_cb(void *src, void *dst, int64_t n) -{ - blender::uninitialized_move_n(static_cast(src), n, static_cast(dst)); -} -template void move_to_uninitialized_indices_cb(void *src, void *dst, IndexMask mask) +template void move_construct_indices_cb(void *src, void *dst, IndexMask mask) { T *src_ = static_cast(src); T *dst_ = static_cast(dst); @@ -122,7 +92,7 @@ template void move_to_uninitialized_indices_cb(void *src, void *dst, mask.foreach_index([&](int64_t i) { new (dst_ + i) T(std::move(src_[i])); }); } -template void relocate_to_initialized_cb(void *src, void *dst) +template void relocate_assign_cb(void *src, void *dst) { T *src_ = static_cast(src); T *dst_ = static_cast(dst); @@ -130,11 +100,7 @@ template void relocate_to_initialized_cb(void *src, void *dst) *dst_ = std::move(*src_); src_->~T(); } -template void relocate_to_initialized_n_cb(void *src, void *dst, int64_t n) -{ - blender::initialized_relocate_n(static_cast(src), n, static_cast(dst)); -} -template void relocate_to_initialized_indices_cb(void *src, void *dst, IndexMask mask) +template void relocate_assign_indices_cb(void *src, void *dst, IndexMask mask) { T *src_ = static_cast(src); T *dst_ = static_cast(dst); @@ -145,7 +111,7 @@ template void relocate_to_initialized_indices_cb(void *src, void *ds }); } -template void relocate_to_uninitialized_cb(void *src, void *dst) +template void relocate_construct_cb(void *src, void *dst) { T *src_ = static_cast(src); T *dst_ = static_cast(dst); @@ -153,12 +119,7 @@ template void relocate_to_uninitialized_cb(void *src, void *dst) new (dst_) T(std::move(*src_)); src_->~T(); } -template void relocate_to_uninitialized_n_cb(void *src, void *dst, int64_t n) -{ - blender::uninitialized_relocate_n(static_cast(src), n, static_cast(dst)); -} -template -void relocate_to_uninitialized_indices_cb(void *src, void *dst, IndexMask mask) +template void relocate_construct_indices_cb(void *src, void *dst, IndexMask mask) { T *src_ = static_cast(src); T *dst_ = static_cast(dst); @@ -169,7 +130,7 @@ void relocate_to_uninitialized_indices_cb(void *src, void *dst, IndexMask mask) }); } -template void fill_initialized_cb(const void *value, void *dst, int64_t n) +template void fill_assign_cb(const void *value, void *dst, int64_t n) { const T &value_ = *static_cast(value); T *dst_ = static_cast(dst); @@ -178,7 +139,7 @@ template void fill_initialized_cb(const void *value, void *dst, int6 dst_[i] = value_; } } -template void fill_initialized_indices_cb(const void *value, void *dst, IndexMask mask) +template void fill_assign_indices_cb(const void *value, void *dst, IndexMask mask) { const T &value_ = *static_cast(value); T *dst_ = static_cast(dst); @@ -186,7 +147,7 @@ template void fill_initialized_indices_cb(const void *value, void *d mask.foreach_index([&](int64_t i) { dst_[i] = value_; }); } -template void fill_uninitialized_cb(const void *value, void *dst, int64_t n) +template void fill_construct_cb(const void *value, void *dst, int64_t n) { const T &value_ = *static_cast(value); T *dst_ = static_cast(dst); @@ -195,8 +156,7 @@ template void fill_uninitialized_cb(const void *value, void *dst, in new (dst_ + i) T(value_); } } -template -void fill_uninitialized_indices_cb(const void *value, void *dst, IndexMask mask) +template void fill_construct_indices_cb(const void *value, void *dst, IndexMask mask) { const T &value_ = *static_cast(value); T *dst_ = static_cast(dst); @@ -204,7 +164,7 @@ void fill_uninitialized_indices_cb(const void *value, void *dst, IndexMask mask) mask.foreach_index([&](int64_t i) { new (dst_ + i) T(value_); }); } -template void debug_print_cb(const void *value, std::stringstream &ss) +template void print_cb(const void *value, std::stringstream &ss) { const T &value_ = *static_cast(value); ss << value_; @@ -225,59 +185,96 @@ template uint64_t hash_cb(const void *value) } // namespace blender::fn::cpp_type_util +/** + * Different types support different features. Features like copy constructibility can be detected + * automatically easily. For some features this is harder as of C++17. Those have flags in this + * enum and need to be determined by the programmer. + */ +enum class CPPTypeFlags { + None = 0, + Hashable = 1 << 0, + Printable = 1 << 1, + EqualityComparable = 1 << 2, + + BasicType = Hashable | Printable | EqualityComparable, +}; +ENUM_OPERATORS(CPPTypeFlags, CPPTypeFlags::EqualityComparable) + namespace blender::fn { -template -inline std::unique_ptr create_cpp_type(StringRef name, const T &default_value) +template +inline std::unique_ptr create_cpp_type(StringRef name) { using namespace cpp_type_util; - const CPPType *type = new CPPType(name, - sizeof(T), - alignof(T), - std::is_trivially_destructible_v, - construct_default_cb, - construct_default_n_cb, - construct_default_indices_cb, - destruct_cb, - destruct_n_cb, - destruct_indices_cb, - copy_to_initialized_cb, - copy_to_initialized_n_cb, - copy_to_initialized_indices_cb, - copy_to_uninitialized_cb, - copy_to_uninitialized_n_cb, - copy_to_uninitialized_indices_cb, - move_to_initialized_cb, - move_to_initialized_n_cb, - move_to_initialized_indices_cb, - move_to_uninitialized_cb, - move_to_uninitialized_n_cb, - move_to_uninitialized_indices_cb, - relocate_to_initialized_cb, - relocate_to_initialized_n_cb, - relocate_to_initialized_indices_cb, - relocate_to_uninitialized_cb, - relocate_to_uninitialized_n_cb, - relocate_to_uninitialized_indices_cb, - fill_initialized_cb, - fill_initialized_indices_cb, - fill_uninitialized_cb, - fill_uninitialized_indices_cb, - debug_print_cb, - is_equal_cb, - hash_cb, - static_cast(&default_value)); + + CPPTypeMembers m; + m.name = name; + m.size = (int64_t)sizeof(T); + m.alignment = (int64_t)alignof(T); + m.is_trivially_destructible = std::is_trivially_destructible_v; + if constexpr (std::is_default_constructible_v) { + m.default_construct = default_construct_cb; + m.default_construct_indices = default_construct_indices_cb; + static T default_value; + m.default_value = (void *)&default_value; + } + if constexpr (std::is_destructible_v) { + m.destruct = destruct_cb; + m.destruct_indices = destruct_indices_cb; + } + if constexpr (std::is_copy_assignable_v) { + m.copy_assign = copy_assign_cb; + m.copy_assign_indices = copy_assign_indices_cb; + } + if constexpr (std::is_copy_constructible_v) { + m.copy_construct = copy_construct_cb; + m.copy_construct_indices = copy_construct_indices_cb; + } + if constexpr (std::is_move_assignable_v) { + m.move_assign = move_assign_cb; + m.move_assign_indices = move_assign_indices_cb; + } + if constexpr (std::is_move_constructible_v) { + m.move_construct = move_construct_cb; + m.move_construct_indices = move_construct_indices_cb; + } + if constexpr (std::is_destructible_v) { + if constexpr (std::is_move_assignable_v) { + m.relocate_assign = relocate_assign_cb; + m.relocate_assign_indices = relocate_assign_indices_cb; + } + if constexpr (std::is_move_constructible_v) { + m.relocate_construct = relocate_construct_cb; + m.relocate_construct_indices = relocate_construct_indices_cb; + } + } + if constexpr (std::is_copy_assignable_v) { + m.fill_assign_indices = fill_assign_indices_cb; + } + if constexpr (std::is_copy_constructible_v) { + m.fill_construct_indices = fill_construct_indices_cb; + } + if constexpr ((bool)(flags & CPPTypeFlags::Hashable)) { + m.hash = hash_cb; + } + if constexpr ((bool)(flags & CPPTypeFlags::Printable)) { + m.print = print_cb; + } + if constexpr ((bool)(flags & CPPTypeFlags::EqualityComparable)) { + m.is_equal = is_equal_cb; + } + + const CPPType *type = new CPPType(std::move(m)); return std::unique_ptr(type); } } // namespace blender::fn -#define MAKE_CPP_TYPE(IDENTIFIER, TYPE_NAME) \ +#define MAKE_CPP_TYPE(IDENTIFIER, TYPE_NAME, FLAGS) \ template<> const blender::fn::CPPType &blender::fn::CPPType::get() \ { \ - static TYPE_NAME default_value; \ - static std::unique_ptr cpp_type = blender::fn::create_cpp_type( \ - STRINGIFY(IDENTIFIER), default_value); \ + static std::unique_ptr cpp_type = \ + blender::fn::create_cpp_type(STRINGIFY(IDENTIFIER)); \ return *cpp_type; \ } \ /* Support using `CPPType::get()`. Otherwise the caller would have to remove const. */ \ -- cgit v1.2.3