aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/armnn/Optional.hpp38
-rw-r--r--src/armnn/test/OptionalTest.cpp39
2 files changed, 76 insertions, 1 deletions
diff --git a/include/armnn/Optional.hpp b/include/armnn/Optional.hpp
index cfe0d30610..116466d013 100644
--- a/include/armnn/Optional.hpp
+++ b/include/armnn/Optional.hpp
@@ -30,6 +30,15 @@ namespace armnn
// to have default value for an Optional in a function declaration.
struct EmptyOptional {};
+// Disambiguation tag that can be passed to the constructor to indicate that
+// the contained object should be constructed in-place
+struct ConstructInPlace
+{
+ explicit ConstructInPlace() = default;
+};
+
+#define CONSTRUCT_IN_PLACE armnn::ConstructInPlace{}
+
// OptionalBase is the common functionality between reference and non-reference
// optional types.
class OptionalBase
@@ -79,6 +88,13 @@ public:
Construct(value);
}
+ template<class... Args>
+ OptionalReferenceSwitch(ConstructInPlace, Args&&... args)
+ : Base{}
+ {
+ Construct(CONSTRUCT_IN_PLACE, std::forward<Args>(args)...);
+ }
+
OptionalReferenceSwitch(const OptionalReferenceSwitch& other)
: Base{}
{
@@ -152,6 +168,13 @@ private:
m_HasValue = true;
}
+ template<class... Args>
+ void Construct(ConstructInPlace, Args&&... args)
+ {
+ new (m_Storage) T(std::forward<Args>(args)...);
+ m_HasValue = true;
+ }
+
alignas(alignof(T)) unsigned char m_Storage[sizeof(T)];
};
@@ -181,6 +204,9 @@ public:
{
}
+ template<class... Args>
+ OptionalReferenceSwitch(ConstructInPlace, Args&&... args) = delete;
+
OptionalReferenceSwitch& operator=(const T value)
{
m_Storage = &value;
@@ -247,6 +273,18 @@ public:
Optional(EmptyOptional empty) : BaseSwitch{empty} {}
Optional(const Optional& other) : BaseSwitch{other} {}
Optional(const BaseSwitch& other) : BaseSwitch{other} {}
+
+ template<class... Args>
+ explicit Optional(ConstructInPlace, Args&&... args) :
+ BaseSwitch(CONSTRUCT_IN_PLACE, std::forward<Args>(args)...) {}
};
+// Utility template that constructs an object of type T in-place and wraps
+// it inside an Optional<T> object
+template<typename T, class... Args>
+Optional<T> MakeOptional(Args&&... args)
+{
+ return Optional<T>(CONSTRUCT_IN_PLACE, std::forward<Args>(args)...);
+}
+
}
diff --git a/src/armnn/test/OptionalTest.cpp b/src/armnn/test/OptionalTest.cpp
index 3f4c02d56f..e2054399f1 100644
--- a/src/armnn/test/OptionalTest.cpp
+++ b/src/armnn/test/OptionalTest.cpp
@@ -54,7 +54,6 @@ BOOST_AUTO_TEST_CASE(SimpleStringTests)
BOOST_TEST(optionalString3.value() == "Hello World");
}
-
BOOST_AUTO_TEST_CASE(StringRefTests)
{
armnn::Optional<std::string&> optionalStringRef{armnn::EmptyOptional()};
@@ -111,4 +110,42 @@ BOOST_AUTO_TEST_CASE(SimpleIntTests)
BOOST_TEST(otherOptionalInt.value() == intValue);
}
+BOOST_AUTO_TEST_CASE(ObjectConstructedInPlaceTests)
+{
+ struct SimpleObject
+ {
+ public:
+ SimpleObject(const std::string& name, int value)
+ : m_Name(name)
+ , m_Value(value)
+ {}
+
+ bool operator ==(const SimpleObject& other)
+ {
+ return m_Name == other.m_Name &&
+ m_Value == other.m_Value;
+ }
+
+ private:
+ std::string m_Name;
+ int m_Value;
+ };
+
+ std::string objectName("SimpleObject");
+ int objectValue = 1;
+ SimpleObject referenceObject(objectName, objectValue);
+
+ // Use MakeOptional
+ armnn::Optional<SimpleObject> optionalObject1 = armnn::MakeOptional<SimpleObject>(objectName, objectValue);
+ BOOST_CHECK(optionalObject1 == true);
+ BOOST_CHECK(optionalObject1.has_value() == true);
+ BOOST_CHECK(optionalObject1.value() == referenceObject);
+
+ // Call in-place constructor directly
+ armnn::Optional<SimpleObject> optionalObject2(CONSTRUCT_IN_PLACE, objectName, objectValue);
+ BOOST_CHECK(optionalObject1 == true);
+ BOOST_CHECK(optionalObject1.has_value() == true);
+ BOOST_CHECK(optionalObject1.value() == referenceObject);
+}
+
BOOST_AUTO_TEST_SUITE_END()