[Bf-blender-cvs] [c4d221b1495] functions: simple BLI::optional<T> type (C++11 compatible)

Jacques Lucke noreply at git.blender.org
Thu Feb 28 14:43:09 CET 2019


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")



More information about the Bf-blender-cvs mailing list