Commit: c4d221b14954b49256c62ff54fca0b5d20539885
Author: Jacques Lucke
Date:   Thu Feb 28 14:18:06 2019 +0100
Branches: functions
https://developer.blender.org/rBc4d221b14954b49256c62ff54fca0b5d20539885

simple BLI::optional<T> type (C++11 compatible)

===================================================================

A       source/blender/blenlib/BLI_optional.hpp
M       source/blender/blenlib/CMakeLists.txt
A       tests/gtests/blenlib/BLI_optional_test.cc
M       tests/gtests/blenlib/CMakeLists.txt

===================================================================

diff --git a/source/blender/blenlib/BLI_optional.hpp 
b/source/blender/blenlib/BLI_optional.hpp
new file mode 100644
index 00000000000..74d6b2960bb
--- /dev/null
+++ b/source/blender/blenlib/BLI_optional.hpp
@@ -0,0 +1,139 @@
+#pragma once
+
+#include "BLI_utildefines.h"
+
+#include <algorithm>
+#include <memory>
+
+namespace BLI {
+
+       template<typename T>
+       class Optional {
+       private:
+               char m_raw_data[sizeof(T)];
+               bool m_set;
+
+       public:
+               Optional()
+                       : m_set(false) {}
+
+               ~Optional()
+               {
+                       this->reset();
+               }
+
+               Optional(T &value)
+                       : Optional()
+               {
+                       this->set(value);
+               }
+
+               Optional(T &&value)
+                       : Optional()
+               {
+                       this->set(value);
+               }
+
+               Optional(const Optional &other)
+               {
+                       if (other.has_value()) {
+                               this->set(other.value());
+                       }
+                       else {
+                               m_set = false;
+                       }
+               }
+
+               Optional(Optional &&other)
+               {
+                       if (other.has_value()) {
+                               this->set(std::move(other.value()));
+                       }
+                       else {
+                               m_set = false;
+                       }
+               }
+
+               Optional &operator=(const Optional &other)
+               {
+                       if (this == &other) {
+                               return *this;
+                       }
+                       if (other.has_value()) {
+                               this->set(other.value());
+                       }
+                       else {
+                               this->reset();
+                       }
+                       return *this;
+               }
+
+               Optional &operator=(Optional &&other)
+               {
+                       if (this == &other) {
+                               return *this;
+                       }
+                       if (other.has_value()) {
+                               this->set(std::move(other.value()));
+                       }
+                       else {
+                               this->reset();
+                       }
+                       return *this;
+               }
+
+               bool has_value() const
+               {
+                       return m_set;
+               }
+
+               T &value() const
+               {
+                       if (m_set) {
+                               return *this->value_ptr();
+                       }
+                       else {
+                               BLI_assert(false);
+                               return *(T *)nullptr;
+                       }
+               }
+
+               void set(T &value)
+               {
+                       if (m_set) {
+                               std::copy_n(&value, 1, this->value_ptr());
+                       }
+                       else {
+                               std::uninitialized_copy_n(&value, 1, 
this->value_ptr());
+                               m_set = true;
+                       }
+               }
+
+               void set(T &&value)
+               {
+                       if (m_set) {
+                               std::copy_n(&value, 1, this->value_ptr());
+                       }
+                       else {
+                               std::uninitialized_copy_n(&value, 1, 
this->value_ptr());
+                       }
+               }
+
+               void reset()
+               {
+                       if (m_set) {
+                               this->value_ptr()->~T();
+                               m_set = false;
+                       }
+               }
+
+
+       private:
+               T *value_ptr() const
+               {
+                       return (T *)m_raw_data;
+               }
+
+       };
+
+} /* namespace BLI */
\ No newline at end of file
diff --git a/source/blender/blenlib/CMakeLists.txt 
b/source/blender/blenlib/CMakeLists.txt
index ebe0a00e368..1c9e59ecad7 100644
--- a/source/blender/blenlib/CMakeLists.txt
+++ b/source/blender/blenlib/CMakeLists.txt
@@ -229,6 +229,7 @@ set(SRC
        BLI_lazy_init.hpp
        BLI_listbase_wrapper.hpp
        BLI_mempool.hpp
+       BLI_optional.hpp
        BLI_shared.hpp
        BLI_small_vector.hpp
        BLI_small_map.hpp
diff --git a/tests/gtests/blenlib/BLI_optional_test.cc 
b/tests/gtests/blenlib/BLI_optional_test.cc
new file mode 100644
index 00000000000..c10ff797722
--- /dev/null
+++ b/tests/gtests/blenlib/BLI_optional_test.cc
@@ -0,0 +1,37 @@
+#include "testing/testing.h"
+#include "BLI_optional.hpp"
+#include <string>
+
+using namespace BLI;
+
+TEST(optional, DefaultConstructor)
+{
+       Optional<int> a;
+       EXPECT_FALSE(a.has_value());
+}
+
+TEST(optional, ValueConstructor)
+{
+       Optional<int> a(5);
+       EXPECT_TRUE(a.has_value());
+       EXPECT_EQ(a.value(), 5);
+}
+
+TEST(optional, CopyConstructor)
+{
+       Optional<std::string> a("Hello");
+       Optional<std::string> b = a;
+       EXPECT_TRUE(a.has_value());
+       EXPECT_TRUE(b.has_value());
+       b.value()[0] = 'T';
+       EXPECT_EQ(a.value(), "Hello");
+       EXPECT_EQ(b.value(), "Tello");
+}
+
+TEST(optional, Reset)
+{
+       Optional<int> a(4);
+       EXPECT_TRUE(a.has_value());
+       a.reset();
+       EXPECT_FALSE(a.has_value());
+}
\ No newline at end of file
diff --git a/tests/gtests/blenlib/CMakeLists.txt 
b/tests/gtests/blenlib/CMakeLists.txt
index be8afd5ff26..fd8b20b92b7 100644
--- a/tests/gtests/blenlib/CMakeLists.txt
+++ b/tests/gtests/blenlib/CMakeLists.txt
@@ -55,6 +55,7 @@ BLENDER_TEST(BLI_math_color "bf_blenlib")
 BLENDER_TEST(BLI_math_geom "bf_blenlib")
 BLENDER_TEST(BLI_memiter "bf_blenlib")
 BLENDER_TEST(BLI_mempool "bf_blenlib")
+BLENDER_TEST(BLI_optional "bf_blenlib")
 BLENDER_TEST(BLI_path_util "${BLI_path_util_extra_libs}")
 BLENDER_TEST(BLI_polyfill_2d "bf_blenlib")
 BLENDER_TEST(BLI_shared "bf_blenlib")

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to