aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAron Virginas-Tar <Aron.Virginas-Tar@arm.com>2019-02-22 17:08:36 +0000
committerAron Virginas-Tar <aron.virginas-tar@arm.com>2019-02-27 13:40:06 +0000
commitb56292c0040aa125cdaafcee1a4299c5cd144200 (patch)
tree3ff8908587d065ee4c621db78d4ea26df6500c3e
parent91c0eff2ff4ff384e013cb69cac1e07e28b9e2b1 (diff)
downloadarmnn-b56292c0040aa125cdaafcee1a4299c5cd144200.tar.gz
IVGCVSW-2759 Add MakeOptional to enable in-place optional object construction
* Added new argument-forwarding in-place constructor to Optional * Added MakeOptional utility template to allow for efficient construction of optional objects Change-Id: Iec9067fc5c3e109a26c4cc2fe8468260637b66c5 Signed-off-by: Aron Virginas-Tar <Aron.Virginas-Tar@arm.com>
-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()