/* -*- C++ -*- * * This file is a part of LEMON, a generic C++ optimization library * * Copyright (C) 2003-2006 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport * (Egervary Research Group on Combinatorial Optimization, EGRES). * * Permission to use, modify and distribute this software is granted * provided that this copyright notice appears in all copies. For * precise terms see the accompanying LICENSE file. * * This software is provided "AS IS" with no warranty of any kind, * express or implied, and with no claim as to its suitability for any * purpose. * */ #ifndef LEMON_BITS_VARIANT_H #define LEMON_BITS_VARIANT_H #include namespace lemon { template struct CTOr { static const bool value = true; }; template <> struct CTOr { static const bool value = false; }; template struct CTAnd { static const bool value = false; }; template <> struct CTAnd { static const bool value = true; }; template struct CTEqual { static const bool value = false; }; template struct CTEqual { static const bool value = true; }; template struct CTLess { static const bool value = left < right; }; template struct CTLess { static const bool value = false; }; template struct CTLess<0, right> { static const bool value = true; }; template <> struct CTLess<0, 0> { static const bool value = false; }; template <> struct CTLess<1, 1> { static const bool value = false; }; template struct CTMaxImpl { static const int value = left; }; template struct CTMaxImpl { static const int value = right; }; template struct CTMax { static const int value = CTMaxImpl::value, left, right>::value; }; /// \brief Simple Variant type with two type /// /// Simple Variant type with two type template class BiVariant { public: typedef _First First; typedef _Second Second; struct WrongStateError : public lemon::LogicError { public: virtual const char* what() const throw() { return "lemon::BiVariant::WrongStateError"; } }; BiVariant() { flag = true; new(reinterpret_cast(data)) First(); } BiVariant(const First& first) { flag = true; new(reinterpret_cast(data)) First(first); } BiVariant(const Second& second) { flag = false; new(reinterpret_cast(data)) Second(second); } BiVariant(const BiVariant& bivariant) { flag = bivariant.flag; if (flag) { new(reinterpret_cast(data)) First(bivariant.first()); } else { new(reinterpret_cast(data)) Second(bivariant.second()); } } ~BiVariant() { destroy(); } BiVariant& setFirst() { destroy(); flag = true; new(reinterpret_cast(data)) First(); return *this; } BiVariant& setFirst(const First& first) { destroy(); flag = true; new(reinterpret_cast(data)) First(first); return *this; } BiVariant& setSecond() { destroy(); flag = false; new(reinterpret_cast(data)) Second(); return *this; } BiVariant& setSecond(const Second& second) { destroy(); flag = false; new(reinterpret_cast(data)) Second(second); return *this; } BiVariant& operator=(const First& first) { return setFirst(first); } BiVariant& operator=(const Second& second) { return setSecond(second); } BiVariant& operator=(const BiVariant& bivariant) { if (this == &bivariant) return *this; destroy(); flag = bivariant.flag; if (flag) { new(reinterpret_cast(data)) First(bivariant.first()); } else { new(reinterpret_cast(data)) Second(bivariant.second()); } return *this; } First& first() { LEMON_ASSERT(flag, WrongStateError()); return *reinterpret_cast(data); } const First& first() const { LEMON_ASSERT(flag, WrongStateError()); return *reinterpret_cast(data); } operator First&() { return first(); } operator const First&() const { return first(); } Second& second() { LEMON_ASSERT(!flag, WrongStateError()); return *reinterpret_cast(data); } const Second& second() const { LEMON_ASSERT(!flag, WrongStateError()); return *reinterpret_cast(data); } operator Second&() { return second(); } operator const Second&() const { return second(); } bool firstState() const { return flag; } bool secondState() const { return !flag; } private: void destroy() { if (flag) { reinterpret_cast(data)->~First(); } else { reinterpret_cast(data)->~Second(); } } char data[CTMax::value]; bool flag; }; } #endif