/* -*- 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. * */ // This file contains a modified version of the enable_if library from BOOST. // See the appropriate copyright notice below. // Boost enable_if library // Copyright 2003 © The Trustees of Indiana University. // Use, modification, and distribution is subject to the Boost Software // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // Authors: Jaakko Järvi (jajarvi at osl.iu.edu) // Jeremiah Willcock (jewillco at osl.iu.edu) // Andrew Lumsdaine (lums at osl.iu.edu) #ifndef LEMON_BITS_UTILITY_H #define LEMON_BITS_UTILITY_H #include ///\file ///\brief Miscellaneous basic utilities /// ///\todo Please rethink the organisation of the basic files like this. ///E.g. this file might be merged with invalid.h. namespace lemon { /// Basic type for defining "tags". A "YES" condition for \c enable_if. /// Basic type for defining "tags". A "YES" condition for \c enable_if. /// ///\sa False /// /// \todo This should go to a separate "basic_types.h" (or something) /// file. struct True { ///\e static const bool value = true; }; /// Basic type for defining "tags". A "NO" condition for \c enable_if. /// Basic type for defining "tags". A "NO" condition for \c enable_if. /// ///\sa True struct False { ///\e static const bool value = false; }; class InvalidType { private: InvalidType(); }; 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* exceptionName() const { 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; }; template struct Wrap { const T &value; Wrap(const T &t) : value(t) {} }; /**************** dummy class to avoid ambiguity ****************/ template struct dummy { dummy(int) {} }; /**************** enable_if from BOOST ****************/ template struct enable_if_c { typedef T type; }; template struct enable_if_c {}; template struct enable_if : public enable_if_c {}; template struct lazy_enable_if_c { typedef typename T::type type; }; template struct lazy_enable_if_c {}; template struct lazy_enable_if : public lazy_enable_if_c {}; template struct disable_if_c { typedef T type; }; template struct disable_if_c {}; template struct disable_if : public disable_if_c {}; template struct lazy_disable_if_c { typedef typename T::type type; }; template struct lazy_disable_if_c {}; template struct lazy_disable_if : public lazy_disable_if_c {}; } // namespace lemon #endif