/*++ Copyright (c) 2006 Microsoft Corporation Module Name: optional.h Abstract: Discriminated union of a type T. It defines the notion of initialized/uninitialized objects. Author: Leonardo de Moura (leonardo) 2006-09-29. Revision History: --*/ #pragma once template class optional { T* m_obj; char m_initialized; void construct(const T & val) { m_initialized = 1; m_obj = alloc(T, val); } void destroy() { if (m_initialized == 1) { dealloc(m_obj); m_obj = nullptr; } m_initialized = 0; } public: optional(): m_obj(nullptr), m_initialized(0) {} explicit optional(const T & val) { construct(val); } optional(T && val) noexcept : m_obj(nullptr), m_initialized(0) { std::swap(m_obj, val.m_obj); std::swap(m_initialized, val.m_initialized); } optional(const optional & val): m_initialized(0) { if (val.m_initialized == 1) { construct(*val); } } ~optional() { destroy(); } static optional const & undef() { static optional u; return u; } bool initialized() const { return m_initialized == 1; } operator bool() const { return m_initialized == 1; } bool operator!() const { return m_initialized == 0; } T * get() const { if (m_initialized == 1) { return m_obj; } else { return 0; } } void set_invalid() { if (m_initialized == 1) { destroy(); } } T * operator->() { SASSERT(m_initialized==1); return m_obj; } T const * operator->() const { SASSERT(m_initialized==1); return m_obj; } const T & operator*() const { SASSERT(m_initialized==1); return *m_obj; } T & operator*() { SASSERT(m_initialized==1); return *m_obj; } optional & operator=(const T & val) { destroy(); construct(val); return * this; } optional & operator=(const optional & val) { if (&val != this) { destroy(); if (val.m_initialized) { construct(*val); } } return *this; } }; /** \brief Template specialization for pointers. NULL represents uninitialized pointers. */ template class optional { T * m_ptr; static optional m_undef; public: optional():m_ptr(nullptr) {} explicit optional(T * val):m_ptr(val) {} optional(const optional & val):m_ptr(val.m_ptr) {} static optional const & undef() { return m_undef; } bool initialized() const { return m_ptr != 0 ; } operator bool() const { return m_ptr != 0; } bool operator!() const { return m_ptr == nullptr; } void reset() { m_ptr = 0; } optional & operator=(T * val) { m_ptr = val; return *this; } optional & operator=(const optional & val) { m_ptr = val.m_ptr; return *this; } T ** operator->() { return &m_ptr; } T * operator*() const { return m_ptr; } T * & operator*() { return m_ptr; } };