#ifndef _TCUMAYBE_HPP #define _TCUMAYBE_HPP /*------------------------------------------------------------------------- * drawElements Quality Program Tester Core * ---------------------------------------- * * Copyright 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *//*! * \file * \brief Template for values that may not exist. *//*--------------------------------------------------------------------*/ #include "tcuDefs.hpp" namespace tcu { // Empty struct used to initialize Maybe objects without providing the type explicitly. struct Nothing_T { explicit constexpr Nothing_T (int) {} }; constexpr Nothing_T Nothing (0); // \note Type T is always aligned to same alignment as deUint64. // \note This type always uses at least sizeof(T*) + sizeof(deUint64) of memory. template class Maybe { public: Maybe (void); Maybe (const Nothing_T&); ~Maybe (void); Maybe (const T& val); Maybe& operator= (const T& val); Maybe (const Maybe& other); Maybe& operator= (const Maybe& other); const T& get (void) const; T& get (void); const T& operator* (void) const { return get(); } T& operator* (void) { return get(); } const T* operator-> (void) const; T* operator-> (void); operator bool (void) const { return !!m_ptr; } private: T* m_ptr; union { deUint8 m_data[sizeof(T)]; deUint64 m_align; }; } DE_WARN_UNUSED_TYPE; template Maybe nothing (void) { return Maybe(); } template Maybe just (const T& value) { return Maybe(value); } template Maybe::Maybe (void) : m_ptr (nullptr) { } template Maybe::Maybe (const Nothing_T&) : m_ptr (nullptr) { } template Maybe::~Maybe (void) { if (m_ptr) m_ptr->~T(); } template Maybe::Maybe (const T& val) : m_ptr (nullptr) { m_ptr = new(m_data)T(val); } template Maybe& Maybe::operator= (const T& val) { if (m_ptr) m_ptr->~T(); m_ptr = new(m_data)T(val); return *this; } template Maybe::Maybe (const Maybe& other) : m_ptr (nullptr) { if (other.m_ptr) m_ptr = new(m_data)T(*other.m_ptr); } template Maybe& Maybe::operator= (const Maybe& other) { if (this == &other) return *this; if (m_ptr) m_ptr->~T(); if (other.m_ptr) m_ptr = new(m_data)T(*other.m_ptr); else m_ptr = nullptr; return *this; } template const T* Maybe::operator-> (void) const { DE_ASSERT(m_ptr); return m_ptr; } template T* Maybe::operator-> (void) { DE_ASSERT(m_ptr); return m_ptr; } template const T& Maybe::get (void) const { DE_ASSERT(m_ptr); return *m_ptr; } template T& Maybe::get (void) { DE_ASSERT(m_ptr); return *m_ptr; } } // tcu #endif // _TCUMAYBE_HPP