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