diff options
author | Hans Goudey <h.goudey@me.com> | 2020-09-01 20:35:14 +0300 |
---|---|---|
committer | Hans Goudey <h.goudey@me.com> | 2020-09-01 20:38:05 +0300 |
commit | baca8611e5fe4b3dcd6f5065fb125bc0a9d65934 (patch) | |
tree | bb1230387cd53b15f9621f10c4d0e5e2050b5580 /source/blender/blenlib/BLI_memory_utils.hh | |
parent | 31705201dddebf7e3be5c4533b89f380aad1ede1 (diff) | |
parent | 2930d4fcea405985f2212c5f28c061af7c4849f8 (diff) |
Merge branch 'master' into active-fcurve-keyframeactive-fcurve-keyframe
Diffstat (limited to 'source/blender/blenlib/BLI_memory_utils.hh')
-rw-r--r-- | source/blender/blenlib/BLI_memory_utils.hh | 56 |
1 files changed, 55 insertions, 1 deletions
diff --git a/source/blender/blenlib/BLI_memory_utils.hh b/source/blender/blenlib/BLI_memory_utils.hh index 7216536a884..49076bb1aae 100644 --- a/source/blender/blenlib/BLI_memory_utils.hh +++ b/source/blender/blenlib/BLI_memory_utils.hh @@ -162,7 +162,7 @@ void uninitialized_convert_n(const From *src, int64_t n, To *dst) int64_t current = 0; try { for (; current < n; current++) { - new (static_cast<void *>(dst + current)) To((To)src[current]); + new (static_cast<void *>(dst + current)) To(static_cast<To>(src[current])); } } catch (...) { @@ -410,6 +410,15 @@ class NoInitialization { }; /** + * This can be used to mark a constructor of an object that does not throw exceptions. Other + * constructors can delegate to this constructor to make sure that the object lifetime starts. + * With this, the destructor of the object will be called, even when the remaining constructor + * throws. + */ +class NoExceptConstructor { +}; + +/** * Helper variable that checks if a pointer type can be converted into another pointer type without * issues. Possible issues are casting away const and casting a pointer to a child class. * Adding const or casting to a parent class is fine. @@ -427,4 +436,49 @@ inline constexpr int64_t default_inline_buffer_capacity(size_t element_size) return (static_cast<int64_t>(element_size) < 100) ? 4 : 0; } +/** + * This can be used by containers to implement an exception-safe copy-assignment-operator. + * It assumes that the container has an exception safe copy constructor and an exception-safe + * move-assignment-operator. + */ +template<typename Container> Container ©_assign_container(Container &dst, const Container &src) +{ + if (&src == &dst) { + return dst; + } + + Container container_copy{src}; + dst = std::move(container_copy); + return dst; +} + +/** + * This can be used by containers to implement an exception-safe move-assignment-operator. + * It assumes that the container has an exception-safe move-constructor and a noexcept constructor + * tagged with the NoExceptConstructor tag. + */ +template<typename Container> +Container &move_assign_container(Container &dst, Container &&src) noexcept( + std::is_nothrow_move_constructible_v<Container>) +{ + if (&dst == &src) { + return dst; + } + + dst.~Container(); + if constexpr (std::is_nothrow_move_constructible_v<Container>) { + new (&dst) Container(std::move(src)); + } + else { + try { + new (&dst) Container(std::move(src)); + } + catch (...) { + new (&dst) Container(NoExceptConstructor()); + throw; + } + } + return dst; +} + } // namespace blender |