#ifndef _TCUEITHER_HPP #define _TCUEITHER_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 class that is either type of First or Second. *//*--------------------------------------------------------------------*/ #include "tcuDefs.hpp" namespace tcu { /*--------------------------------------------------------------------*//*! * \brief Object containing Either First or Second type of object * * \note Type First and Second are always aligned to same alignment as * deUint64. * \note This type always uses at least sizeof(bool) + max(sizeof(First*), * sizeof(Second*)) + sizeof(deUint64) of memory. *//*--------------------------------------------------------------------*/ template class Either { public: Either (const First& first); Either (const Second& second); ~Either (void); Either (const Either& other); Either& operator= (const Either& other); Either& operator= (const First& first); Either& operator= (const Second& second); bool isFirst (void) const; bool isSecond (void) const; const First& getFirst (void) const; const Second& getSecond (void) const; template const Type& get (void) const; template bool is (void) const; private: void release (void); bool m_isFirst; union { First* m_first; Second* m_second; }; union { deUint8 m_data[sizeof(First) > sizeof(Second) ? sizeof(First) : sizeof(Second)]; deUint64 m_align; }; } DE_WARN_UNUSED_TYPE; namespace EitherDetail { template struct Get; template struct Get { static const First& get (const Either& either) { return either.getFirst(); } }; template struct Get { static const Second& get (const Either& either) { return either.getSecond(); } }; template const Type& get (const Either& either) { return Get::get(either); } template struct Is; template struct Is { static bool is (const Either& either) { return either.isFirst(); } }; template struct Is { static bool is (const Either& either) { return either.isSecond(); } }; template bool is (const Either& either) { return Is::is(either); } } // EitherDetail template void Either::release (void) { if (m_isFirst) m_first->~First(); else m_second->~Second(); m_isFirst = true; m_first = DE_NULL; } template Either::Either (const First& first) : m_isFirst (true) { m_first = new(m_data)First(first); } template Either::Either (const Second& second) : m_isFirst (false) { m_second = new(m_data)Second(second); } template Either::~Either (void) { release(); } template Either::Either (const Either& other) : m_isFirst (other.m_isFirst) { if (m_isFirst) m_first = new(m_data)First(*other.m_first); else m_second = new(m_data)Second(*other.m_second); } template Either& Either::operator= (const Either& other) { if (this == &other) return *this; release(); m_isFirst = other.m_isFirst; if (m_isFirst) m_first = new(m_data)First(*other.m_first); else m_second = new(m_data)Second(*other.m_second); return *this; } template Either& Either::operator= (const First& first) { release(); m_isFirst = true; m_first = new(m_data)First(first); return *this; } template Either& Either::operator= (const Second& second) { release(); m_isFirst = false; m_second = new(m_data)Second(second); return *this; } template bool Either::isFirst (void) const { return m_isFirst; } template bool Either::isSecond (void) const { return !m_isFirst; } template const First& Either::getFirst (void) const { DE_ASSERT(isFirst()); return *m_first; } template const Second& Either::getSecond (void) const { DE_ASSERT(isSecond()); return *m_second; } template template const Type& Either::get (void) const { return EitherDetail::get(*this); } template template bool Either::is (void) const { return EitherDetail::is(*this); } void Either_selfTest (void); } // tcu #endif // _TCUEITHER_HPP