// // Copyright © 2017 Arm Ltd. All rights reserved. // SPDX-License-Identifier: MIT // #pragma once #include "Exceptions.hpp" namespace armnn { // NOTE: the members of the Optional class don't follow the ArmNN // coding convention because the interface to be close to // the C++-17 interface so we can easily migrate to std::optional // later. template class Optional final { public: Optional(T&& value) : m_HasValue{true} { new (m_Storage) T(value); } Optional(const T& value) : m_HasValue{true} { new (m_Storage) T(value); } Optional(const Optional& other) : m_HasValue{false} { *this = other; } Optional() noexcept : m_HasValue{false} { } ~Optional() { reset(); } operator bool() const noexcept { return has_value(); } Optional& operator=(T&& value) { reset(); new (m_Storage) T(value); m_HasValue = true; return *this; } Optional& operator=(const T& value) { reset(); new(m_Storage) T(value); m_HasValue = true; return *this; } Optional& operator=(const Optional& other) { reset(); if (other.has_value()) { new (m_Storage) T(other.value()); m_HasValue = true; } return *this; } const T& value() const { if (!has_value()) { throw BadOptionalAccessException("Optional has no value"); } auto valuePtr = reinterpret_cast(m_Storage); return *valuePtr; } T& value() { if (!has_value()) { throw BadOptionalAccessException("Optional has no value"); } auto valuePtr = reinterpret_cast(m_Storage); return *valuePtr; } bool has_value() const noexcept { return m_HasValue; } void reset() { if (has_value()) { value().T::~T(); m_HasValue = false; } } private: alignas(alignof(T)) unsigned char m_Storage[sizeof(T)]; bool m_HasValue; }; }