From b56292c0040aa125cdaafcee1a4299c5cd144200 Mon Sep 17 00:00:00 2001 From: Aron Virginas-Tar Date: Fri, 22 Feb 2019 17:08:36 +0000 Subject: 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 --- include/armnn/Optional.hpp | 38 ++++++++++++++++++++++++++++++++++++++ src/armnn/test/OptionalTest.cpp | 39 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 76 insertions(+), 1 deletion(-) 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 + OptionalReferenceSwitch(ConstructInPlace, Args&&... args) + : Base{} + { + Construct(CONSTRUCT_IN_PLACE, std::forward(args)...); + } + OptionalReferenceSwitch(const OptionalReferenceSwitch& other) : Base{} { @@ -152,6 +168,13 @@ private: m_HasValue = true; } + template + void Construct(ConstructInPlace, Args&&... args) + { + new (m_Storage) T(std::forward(args)...); + m_HasValue = true; + } + alignas(alignof(T)) unsigned char m_Storage[sizeof(T)]; }; @@ -181,6 +204,9 @@ public: { } + template + 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 + explicit Optional(ConstructInPlace, Args&&... args) : + BaseSwitch(CONSTRUCT_IN_PLACE, std::forward(args)...) {} }; +// Utility template that constructs an object of type T in-place and wraps +// it inside an Optional object +template +Optional MakeOptional(Args&&... args) +{ + return Optional(CONSTRUCT_IN_PLACE, std::forward(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 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 optionalObject1 = armnn::MakeOptional(objectName, objectValue); + BOOST_CHECK(optionalObject1 == true); + BOOST_CHECK(optionalObject1.has_value() == true); + BOOST_CHECK(optionalObject1.value() == referenceObject); + + // Call in-place constructor directly + armnn::Optional 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() -- cgit v1.2.1