lemon/bits/utility.h
changeset 2309 468a525d5b45
parent 2151 38ec4a930c05
child 2386 81b47fc5c444
equal deleted inserted replaced
3:350368d38e7a 4:c4c71397e313
    32 //             Andrew Lumsdaine (lums at osl.iu.edu)
    32 //             Andrew Lumsdaine (lums at osl.iu.edu)
    33 
    33 
    34 
    34 
    35 #ifndef LEMON_BITS_UTILITY_H
    35 #ifndef LEMON_BITS_UTILITY_H
    36 #define LEMON_BITS_UTILITY_H
    36 #define LEMON_BITS_UTILITY_H
    37 
       
    38 #include <lemon/error.h>
       
    39 
    37 
    40 ///\file
    38 ///\file
    41 ///\brief Miscellaneous basic utilities
    39 ///\brief Miscellaneous basic utilities
    42 ///
    40 ///
    43 ///\todo Please rethink the organisation of the basic files like this.
    41 ///\todo Please rethink the organisation of the basic files like this.
    72 
    70 
    73 
    71 
    74   class InvalidType {
    72   class InvalidType {
    75   private:
    73   private:
    76     InvalidType();
    74     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   };
    75   };
   288 
    76 
   289   template <typename T>
    77   template <typename T>
   290   struct Wrap {
    78   struct Wrap {
   291     const T &value;
    79     const T &value;