lemon/bits/utility.h
author alpar
Wed, 09 Aug 2006 12:51:21 +0000
changeset 2170 42fffa713424
parent 2078 123f08422c14
child 2177 416a7030b7e3
permissions -rw-r--r--
Do not list the header itself.
     1 /* -*- C++ -*-
     2  *
     3  * This file is a part of LEMON, a generic C++ optimization library
     4  *
     5  * Copyright (C) 2003-2006
     6  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     7  * (Egervary Research Group on Combinatorial Optimization, EGRES).
     8  *
     9  * Permission to use, modify and distribute this software is granted
    10  * provided that this copyright notice appears in all copies. For
    11  * precise terms see the accompanying LICENSE file.
    12  *
    13  * This software is provided "AS IS" with no warranty of any kind,
    14  * express or implied, and with no claim as to its suitability for any
    15  * purpose.
    16  *
    17  */
    18 
    19 // This file contains a modified version of the enable_if library from BOOST.
    20 // See the appropriate copyright notice below.
    21 
    22 // Boost enable_if library
    23 
    24 // Copyright 2003 © The Trustees of Indiana University.
    25 
    26 // Use, modification, and distribution is subject to the Boost Software
    27 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
    28 // http://www.boost.org/LICENSE_1_0.txt)
    29 
    30 //    Authors: Jaakko Järvi (jajarvi at osl.iu.edu)
    31 //             Jeremiah Willcock (jewillco at osl.iu.edu)
    32 //             Andrew Lumsdaine (lums at osl.iu.edu)
    33 
    34 
    35 #ifndef LEMON_BITS_UTILITY_H
    36 #define LEMON_BITS_UTILITY_H
    37 
    38 #include <lemon/error.h>
    39 
    40 ///\file
    41 ///\brief Miscellaneous basic utilities
    42 ///
    43 ///\todo Please rethink the organisation of the basic files like this.
    44 ///E.g. this file might be merged with invalid.h.
    45 
    46 
    47 namespace lemon
    48 {
    49 
    50   /// Basic type for defining "tags". A "YES" condition for \c enable_if.
    51 
    52   /// Basic type for defining "tags". A "YES" condition for \c enable_if.
    53   ///
    54   ///\sa False
    55   ///
    56   /// \todo This should go to a separate "basic_types.h" (or something)
    57   /// file.
    58   struct True {
    59     ///\e
    60     static const bool value = true;
    61   };
    62 
    63   /// Basic type for defining "tags". A "NO" condition for \c enable_if.
    64 
    65   /// Basic type for defining "tags". A "NO" condition for \c enable_if.
    66   ///
    67   ///\sa True
    68   struct False {
    69     ///\e
    70     static const bool value = false;
    71   };
    72 
    73 
    74   class InvalidType {
    75   private:
    76     InvalidType();
    77   };
    78 
    79   template <bool left, bool right>
    80   struct CTOr {
    81     static const bool value = true;
    82   };
    83 
    84   template <>
    85   struct CTOr<false, false> {
    86     static const bool value = false;
    87   };
    88 
    89   template <bool left, bool right>
    90   struct CTAnd {
    91     static const bool value = false;
    92   };
    93 
    94   template <>
    95   struct CTAnd<true, true> {
    96     static const bool value = true;
    97   };
    98 
    99   template <int left, int right>
   100   struct CTEqual {
   101     static const bool value = false;
   102   };
   103 
   104   template <int val>
   105   struct CTEqual<val, val> {
   106     static const bool value = true;
   107   };
   108 
   109 
   110   template <int left, int right>
   111   struct CTLess {
   112     static const bool value = left < right;
   113   };
   114 
   115   template <int left>
   116   struct CTLess<left, 0> {
   117     static const bool value = false;
   118   };
   119 
   120   template <int right>
   121   struct CTLess<0, right> {
   122     static const bool value = true;
   123   };
   124 
   125   template <>
   126   struct CTLess<0, 0> {
   127     static const bool value = false;
   128   };
   129 
   130   template <>
   131   struct CTLess<1, 1> {
   132     static const bool value = false;
   133   };
   134 
   135   template <bool less, int left, int right>
   136   struct CTMaxImpl {
   137     static const int value = left;    
   138   };
   139 
   140   template <int left, int right>
   141   struct CTMaxImpl<true, left, right> {
   142     static const int value = right;
   143   };
   144   
   145   template <int left, int right>
   146   struct CTMax {
   147     static const int value = 
   148     CTMaxImpl<CTLess<left, right>::value, left, right>::value;
   149   };
   150 
   151 
   152   /// \brief Simple Variant type with two type
   153   ///
   154   /// Simple Variant type with two type
   155   template <typename _First, typename _Second>
   156   class BiVariant {
   157   public:
   158 
   159     typedef _First First;
   160     typedef _Second Second;
   161 
   162     struct WrongStateError : public lemon::LogicError {
   163     public:
   164       virtual const char* what() const throw() {
   165         return "lemon::BiVariant::WrongStateError";
   166       }
   167     };
   168 
   169     BiVariant() {
   170       flag = true;
   171       new(reinterpret_cast<First*>(data)) First();
   172     }
   173 
   174     BiVariant(const First& first) {
   175       flag = true;
   176       new(reinterpret_cast<First*>(data)) First(first);
   177     }
   178 
   179     BiVariant(const Second& second) {
   180       flag = false;
   181       new(reinterpret_cast<Second*>(data)) Second(second);
   182     }
   183 
   184     BiVariant(const BiVariant& bivariant) {
   185       flag = bivariant.flag;
   186       if (flag) {
   187         new(reinterpret_cast<First*>(data)) First(bivariant.first());      
   188       } else {
   189         new(reinterpret_cast<Second*>(data)) Second(bivariant.second());      
   190       }
   191     }
   192 
   193     ~BiVariant() {
   194       destroy();
   195     }
   196 
   197     BiVariant& setFirst() {
   198       destroy();
   199       flag = true;
   200       new(reinterpret_cast<First*>(data)) First();   
   201       return *this;
   202     }
   203 
   204     BiVariant& setFirst(const First& first) {
   205       destroy();
   206       flag = true;
   207       new(reinterpret_cast<First*>(data)) First(first);   
   208       return *this;
   209     }
   210 
   211     BiVariant& setSecond() {
   212       destroy();
   213       flag = false;
   214       new(reinterpret_cast<Second*>(data)) Second();   
   215       return *this;
   216     }
   217 
   218     BiVariant& setSecond(const Second& second) {
   219       destroy();
   220       flag = false;
   221       new(reinterpret_cast<Second*>(data)) Second(second);   
   222       return *this;
   223     }
   224 
   225     BiVariant& operator=(const First& first) {
   226       return setFirst(first);
   227     }
   228 
   229     BiVariant& operator=(const Second& second) {
   230       return setSecond(second);
   231     }
   232 
   233 
   234     BiVariant& operator=(const BiVariant& bivariant) {
   235       if (this == &bivariant) return *this;
   236       destroy();
   237       flag = bivariant.flag;
   238       if (flag) {
   239         new(reinterpret_cast<First*>(data)) First(bivariant.first());      
   240       } else {
   241         new(reinterpret_cast<Second*>(data)) Second(bivariant.second());      
   242       }
   243       return *this;
   244     }
   245 
   246     First& first() {
   247       LEMON_ASSERT(flag, WrongStateError());
   248       return *reinterpret_cast<First*>(data); 
   249     }
   250 
   251     const First& first() const { 
   252       LEMON_ASSERT(flag, WrongStateError());
   253       return *reinterpret_cast<const First*>(data); 
   254     }
   255 
   256     operator First&() { return first(); }
   257     operator const First&() const { return first(); }
   258 
   259     Second& second() { 
   260       LEMON_ASSERT(!flag, WrongStateError());
   261       return *reinterpret_cast<Second*>(data); 
   262     }
   263 
   264     const Second& second() const { 
   265       LEMON_ASSERT(!flag, WrongStateError());
   266       return *reinterpret_cast<const Second*>(data); 
   267     }
   268 
   269     operator Second&() { return second(); }
   270     operator const Second&() const { return second(); }
   271 
   272     bool firstState() const { return flag; }
   273     bool secondState() const { return !flag; }
   274 
   275   private:
   276 
   277     void destroy() {
   278       if (flag) {
   279         reinterpret_cast<First*>(data)->~First();
   280       } else {
   281         reinterpret_cast<Second*>(data)->~Second();
   282       }
   283     }
   284     
   285     char data[CTMax<sizeof(First), sizeof(Second)>::value];
   286     bool flag;
   287   };
   288 
   289   template <typename T>
   290   struct Wrap {
   291     const T &value;
   292     Wrap(const T &t) : value(t) {}
   293   };
   294 
   295   /**************** dummy class to avoid ambiguity ****************/
   296 
   297   template<int T> struct dummy { dummy(int) {} };
   298 
   299   /**************** enable_if from BOOST ****************/
   300  
   301   template <bool B, class T = void>
   302   struct enable_if_c {
   303     typedef T type;
   304   };
   305 
   306   template <class T>
   307   struct enable_if_c<false, T> {};
   308 
   309   template <class Cond, class T = void> 
   310   struct enable_if : public enable_if_c<Cond::value, T> {};
   311 
   312   template <bool B, class T>
   313   struct lazy_enable_if_c {
   314     typedef typename T::type type;
   315   };
   316 
   317   template <class T>
   318   struct lazy_enable_if_c<false, T> {};
   319 
   320   template <class Cond, class T> 
   321   struct lazy_enable_if : public lazy_enable_if_c<Cond::value, T> {};
   322 
   323 
   324   template <bool B, class T = void>
   325   struct disable_if_c {
   326     typedef T type;
   327   };
   328 
   329   template <class T>
   330   struct disable_if_c<true, T> {};
   331 
   332   template <class Cond, class T = void> 
   333   struct disable_if : public disable_if_c<Cond::value, T> {};
   334 
   335   template <bool B, class T>
   336   struct lazy_disable_if_c {
   337     typedef typename T::type type;
   338   };
   339 
   340   template <class T>
   341   struct lazy_disable_if_c<true, T> {};
   342 
   343   template <class Cond, class T> 
   344   struct lazy_disable_if : public lazy_disable_if_c<Cond::value, T> {};
   345 
   346 } // namespace lemon
   347 
   348 #endif