#pragma once /** * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ #include namespace Aws { namespace Crt { template class Optional { public: Optional() : m_value(nullptr) {} Optional(const T &val) { new (&m_storage) T(val); m_value = reinterpret_cast(&m_storage); } Optional(T &&val) { new (&m_storage) T(std::forward(val)); m_value = reinterpret_cast(&m_storage); } ~Optional() { if (m_value) { m_value->~T(); } } template Optional &operator=(U &&u) { if (m_value) { *m_value = std::forward(u); return *this; } new (&m_storage) T(std::forward(u)); m_value = reinterpret_cast(&m_storage); return *this; } Optional(const Optional &other) { if (other.m_value) { new (&m_storage) T(*other.m_value); m_value = reinterpret_cast(&m_storage); } else { m_value = nullptr; } } Optional(Optional &&other) { if (other.m_value) { new (&m_storage) T(std::forward(*other.m_value)); m_value = reinterpret_cast(&m_storage); } else { m_value = nullptr; } } Optional &operator=(const Optional &other) { if (this == &other) { return *this; } if (m_value) { if (other.m_value) { *m_value = *other.m_value; } else { m_value->~T(); m_value = nullptr; } return *this; } if (other.m_value) { new (&m_storage) T(*other.m_value); m_value = reinterpret_cast(&m_storage); } return *this; } template Optional &operator=(const Optional &other) { if (this == &other) { return *this; } if (m_value) { if (other.m_value) { *m_value = *other.m_value; } else { m_value->~T(); m_value = nullptr; } return *this; } if (other.m_value) { new (&m_storage) T(*other.m_value); m_value = reinterpret_cast(&m_storage); } return *this; } template Optional &operator=(Optional &&other) { if (this == &other) { return *this; } if (m_value) { if (other.m_value) { *m_value = std::forward(*other.m_value); } else { m_value->~T(); m_value = nullptr; } return *this; } if (other.m_value) { new (&m_storage) T(std::forward(*other.m_value)); m_value = reinterpret_cast(&m_storage); } return *this; } const T *operator->() const { return m_value; } T *operator->() { return m_value; } const T &operator*() const & { return *m_value; } T &operator*() & { return *m_value; } const T &&operator*() const && { return std::move(*m_value); } T &&operator*() && { return std::move(*m_value); } explicit operator bool() const noexcept { return m_value != nullptr; } bool has_value() const noexcept { return m_value != nullptr; } T &value() & { return *m_value; } const T &value() const & { return *m_value; } T &&value() && { return std::move(*m_value); } const T &&value() const && { return std::move(*m_value); } private: typename std::aligned_storage::type m_storage; T *m_value; }; } // namespace Crt } // namespace Aws