deba@1993: /* -*- C++ -*- deba@1993: * deba@1993: * This file is a part of LEMON, a generic C++ optimization library deba@1993: * deba@1993: * Copyright (C) 2003-2006 deba@1993: * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport deba@1993: * (Egervary Research Group on Combinatorial Optimization, EGRES). deba@1993: * deba@1993: * Permission to use, modify and distribute this software is granted deba@1993: * provided that this copyright notice appears in all copies. For deba@1993: * precise terms see the accompanying LICENSE file. deba@1993: * deba@1993: * This software is provided "AS IS" with no warranty of any kind, deba@1993: * express or implied, and with no claim as to its suitability for any deba@1993: * purpose. deba@1993: * deba@1993: */ deba@1993: deba@1993: // This file contains a modified version of the enable_if library from BOOST. deba@1993: // See the appropriate copyright notice below. deba@1993: deba@1993: // Boost enable_if library deba@1993: deba@1993: // Copyright 2003 © The Trustees of Indiana University. deba@1993: deba@1993: // Use, modification, and distribution is subject to the Boost Software deba@1993: // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at deba@1993: // http://www.boost.org/LICENSE_1_0.txt) deba@1993: deba@1993: // Authors: Jaakko Järvi (jajarvi at osl.iu.edu) deba@1993: // Jeremiah Willcock (jewillco at osl.iu.edu) deba@1993: // Andrew Lumsdaine (lums at osl.iu.edu) deba@1993: deba@1993: deba@1993: #ifndef LEMON_BITS_UTILITY_H deba@1993: #define LEMON_BITS_UTILITY_H deba@1993: deba@2077: #include deba@2077: deba@1993: ///\file deba@1993: ///\brief Miscellaneous basic utilities deba@1993: /// deba@1993: ///\todo Please rethink the organisation of the basic files like this. deba@1993: ///E.g. this file might be merged with invalid.h. deba@1993: deba@1993: deba@1993: namespace lemon deba@1993: { deba@1993: deba@1993: /// Basic type for defining "tags". A "YES" condition for \c enable_if. deba@1993: deba@1993: /// Basic type for defining "tags". A "YES" condition for \c enable_if. deba@1993: /// deba@1993: ///\sa False deba@1993: /// deba@1993: /// \todo This should go to a separate "basic_types.h" (or something) deba@1993: /// file. deba@1993: struct True { deba@1993: ///\e deba@1993: static const bool value = true; deba@1993: }; deba@1993: deba@1993: /// Basic type for defining "tags". A "NO" condition for \c enable_if. deba@1993: deba@1993: /// Basic type for defining "tags". A "NO" condition for \c enable_if. deba@1993: /// deba@1993: ///\sa True deba@1993: struct False { deba@1993: ///\e deba@1993: static const bool value = false; deba@1993: }; deba@1993: deba@1993: deba@1993: class InvalidType { deba@1993: private: deba@1993: InvalidType(); deba@1993: }; deba@2077: deba@2077: template deba@2077: struct CTOr { deba@2077: static const bool value = true; deba@2077: }; deba@2077: deba@2077: template <> deba@2077: struct CTOr { deba@2077: static const bool value = false; deba@2077: }; deba@2077: deba@2077: template deba@2077: struct CTAnd { deba@2077: static const bool value = false; deba@2077: }; deba@2077: deba@2077: template <> deba@2077: struct CTAnd { deba@2077: static const bool value = true; deba@2077: }; deba@2077: deba@2077: template deba@2077: struct CTEqual { deba@2077: static const bool value = false; deba@2077: }; deba@2077: deba@2077: template deba@2077: struct CTEqual { deba@2077: static const bool value = true; deba@2077: }; deba@2077: deba@2077: deba@2077: template deba@2077: struct CTLess { deba@2078: static const bool value = left < right; deba@2077: }; deba@2077: deba@2077: template deba@2077: struct CTLess { deba@2077: static const bool value = false; deba@2077: }; deba@2077: deba@2077: template deba@2077: struct CTLess<0, right> { deba@2077: static const bool value = true; deba@2077: }; deba@2077: deba@2077: template <> deba@2077: struct CTLess<0, 0> { deba@2077: static const bool value = false; deba@2077: }; deba@2077: deba@2077: template <> deba@2077: struct CTLess<1, 1> { deba@2077: static const bool value = false; deba@2077: }; deba@2077: deba@2077: template deba@2077: struct CTMaxImpl { deba@2077: static const int value = left; deba@2077: }; deba@2077: deba@2077: template deba@2077: struct CTMaxImpl { deba@2077: static const int value = right; deba@2077: }; deba@1993: deba@2077: template deba@2077: struct CTMax { deba@2077: static const int value = deba@2077: CTMaxImpl::value, left, right>::value; deba@2077: }; deba@2077: deba@2077: deba@2077: /// \brief Simple Variant type with two type deba@2077: /// deba@2077: /// Simple Variant type with two type deba@2077: template deba@2077: class BiVariant { deba@2077: public: deba@2077: deba@2077: typedef _First First; deba@2077: typedef _Second Second; deba@2077: deba@2077: struct WrongStateError : public lemon::LogicError { deba@2077: public: deba@2077: virtual const char* exceptionName() const { deba@2077: return "lemon::BiVariant::WrongStateError"; deba@2077: } deba@2077: }; deba@2077: deba@2077: BiVariant() { deba@2077: flag = true; deba@2077: new(reinterpret_cast(data)) First(); deba@2077: } deba@2077: deba@2077: BiVariant(const First& first) { deba@2077: flag = true; deba@2077: new(reinterpret_cast(data)) First(first); deba@2077: } deba@2077: deba@2077: BiVariant(const Second& second) { deba@2077: flag = false; deba@2077: new(reinterpret_cast(data)) Second(second); deba@2077: } deba@2077: deba@2077: BiVariant(const BiVariant& bivariant) { deba@2077: flag = bivariant.flag; deba@2077: if (flag) { deba@2077: new(reinterpret_cast(data)) First(bivariant.first()); deba@2077: } else { deba@2077: new(reinterpret_cast(data)) Second(bivariant.second()); deba@2077: } deba@2077: } deba@2077: deba@2077: ~BiVariant() { deba@2077: destroy(); deba@2077: } deba@2077: deba@2077: BiVariant& setFirst() { deba@2077: destroy(); deba@2077: flag = true; deba@2077: new(reinterpret_cast(data)) First(); deba@2077: return *this; deba@2077: } deba@2077: deba@2077: BiVariant& setFirst(const First& first) { deba@2077: destroy(); deba@2077: flag = true; deba@2077: new(reinterpret_cast(data)) First(first); deba@2077: return *this; deba@2077: } deba@2077: deba@2077: BiVariant& setSecond() { deba@2077: destroy(); deba@2077: flag = false; deba@2077: new(reinterpret_cast(data)) Second(); deba@2077: return *this; deba@2077: } deba@2077: deba@2077: BiVariant& setSecond(const Second& second) { deba@2077: destroy(); deba@2077: flag = false; deba@2077: new(reinterpret_cast(data)) Second(second); deba@2077: return *this; deba@2077: } deba@2077: deba@2077: BiVariant& operator=(const First& first) { deba@2077: return setFirst(first); deba@2077: } deba@2077: deba@2077: BiVariant& operator=(const Second& second) { deba@2077: return setSecond(second); deba@2077: } deba@2077: deba@2077: deba@2077: BiVariant& operator=(const BiVariant& bivariant) { deba@2077: if (this == &bivariant) return *this; deba@2077: destroy(); deba@2077: flag = bivariant.flag; deba@2077: if (flag) { deba@2077: new(reinterpret_cast(data)) First(bivariant.first()); deba@2077: } else { deba@2077: new(reinterpret_cast(data)) Second(bivariant.second()); deba@2077: } deba@2077: return *this; deba@2077: } deba@2077: deba@2077: First& first() { deba@2077: LEMON_ASSERT(flag, WrongStateError()); deba@2077: return *reinterpret_cast(data); deba@2077: } deba@2077: deba@2077: const First& first() const { deba@2077: LEMON_ASSERT(flag, WrongStateError()); deba@2077: return *reinterpret_cast(data); deba@2077: } deba@2077: deba@2077: operator First&() { return first(); } deba@2077: operator const First&() const { return first(); } deba@2077: deba@2077: Second& second() { deba@2077: LEMON_ASSERT(!flag, WrongStateError()); deba@2077: return *reinterpret_cast(data); deba@2077: } deba@2077: deba@2077: const Second& second() const { deba@2077: LEMON_ASSERT(!flag, WrongStateError()); deba@2077: return *reinterpret_cast(data); deba@2077: } deba@2077: deba@2077: operator Second&() { return second(); } deba@2077: operator const Second&() const { return second(); } deba@2077: deba@2077: bool firstState() const { return flag; } deba@2077: bool secondState() const { return !flag; } deba@2077: deba@2077: private: deba@2077: deba@2077: void destroy() { deba@2077: if (flag) { deba@2077: reinterpret_cast(data)->~First(); deba@2077: } else { deba@2077: reinterpret_cast(data)->~Second(); deba@2077: } deba@2077: } deba@2077: deba@2077: char data[CTMax::value]; deba@2077: bool flag; deba@2077: }; deba@1993: deba@1993: template deba@1993: struct Wrap { deba@1993: const T &value; deba@1993: Wrap(const T &t) : value(t) {} deba@1993: }; deba@1993: deba@1993: /**************** dummy class to avoid ambiguity ****************/ deba@1993: deba@1993: template struct dummy { dummy(int) {} }; deba@1993: deba@1993: /**************** enable_if from BOOST ****************/ deba@1993: deba@1993: template deba@1993: struct enable_if_c { deba@1993: typedef T type; deba@1993: }; deba@1993: deba@1993: template deba@1993: struct enable_if_c {}; deba@1993: deba@1993: template deba@1993: struct enable_if : public enable_if_c {}; deba@1993: deba@1993: template deba@1993: struct lazy_enable_if_c { deba@1993: typedef typename T::type type; deba@1993: }; deba@1993: deba@1993: template deba@1993: struct lazy_enable_if_c {}; deba@1993: deba@1993: template deba@1993: struct lazy_enable_if : public lazy_enable_if_c {}; deba@1993: deba@1993: deba@1993: template deba@1993: struct disable_if_c { deba@1993: typedef T type; deba@1993: }; deba@1993: deba@1993: template deba@1993: struct disable_if_c {}; deba@1993: deba@1993: template deba@1993: struct disable_if : public disable_if_c {}; deba@1993: deba@1993: template deba@1993: struct lazy_disable_if_c { deba@1993: typedef typename T::type type; deba@1993: }; deba@1993: deba@1993: template deba@1993: struct lazy_disable_if_c {}; deba@1993: deba@1993: template deba@1993: struct lazy_disable_if : public lazy_disable_if_c {}; deba@1993: deba@1993: } // namespace lemon deba@1993: deba@1993: #endif