COIN-OR::LEMON - Graph Library

Changeset 2077:d687c0033bb5 in lemon-0.x


Ignore:
Timestamp:
05/12/06 11:52:28 (13 years ago)
Author:
Balazs Dezso
Branch:
default
Phase:
public
Convert:
svn:c9d7d8f5-90d6-0310-b91f-818b3a526b0e/lemon/trunk@2740
Message:

Two state Variant
+ Some Compile Time arithmetic

File:
1 edited

Legend:

Unmodified
Added
Removed
  • lemon/bits/utility.h

    r1993 r2077  
    3535#ifndef LEMON_BITS_UTILITY_H
    3636#define LEMON_BITS_UTILITY_H
     37
     38#include <lemon/error.h>
    3739
    3840///\file
     
    7476    InvalidType();
    7577  };
     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  template <bool sless, bool sequal, bool bless>
     110  struct CTLessImpl {
     111   static const bool value =
     112   CTOr<sless, CTAnd<sequal, bless>::value>::value;
     113  };
     114
     115  template <int left, int right>
     116  struct CTLess {
     117    static const bool value =
     118    CTLessImpl<CTLess<left >> 1, right >> 1>::value,
     119               CTEqual<left >> 1, right >> 1>::value,
     120               CTLess<left & 1, right & 1>::value >::value;
     121  };
     122
     123  template <int left>
     124  struct CTLess<left, 0> {
     125    static const bool value = false;
     126  };
     127
     128  template <int right>
     129  struct CTLess<0, right> {
     130    static const bool value = true;
     131  };
     132
     133  template <>
     134  struct CTLess<0, 0> {
     135    static const bool value = false;
     136  };
     137
     138  template <>
     139  struct CTLess<1, 1> {
     140    static const bool value = false;
     141  };
     142
     143  template <bool less, int left, int right>
     144  struct CTMaxImpl {
     145    static const int value = left;   
     146  };
     147
     148  template <int left, int right>
     149  struct CTMaxImpl<true, left, right> {
     150    static const int value = right;
     151  };
    76152 
     153  template <int left, int right>
     154  struct CTMax {
     155    static const int value =
     156    CTMaxImpl<CTLess<left, right>::value, left, right>::value;
     157  };
     158
     159
     160  /// \brief Simple Variant type with two type
     161  ///
     162  /// Simple Variant type with two type
     163  template <typename _First, typename _Second>
     164  class BiVariant {
     165  public:
     166
     167    typedef _First First;
     168    typedef _Second Second;
     169
     170    struct WrongStateError : public lemon::LogicError {
     171    public:
     172      virtual const char* exceptionName() const {
     173        return "lemon::BiVariant::WrongStateError";
     174      }
     175    };
     176
     177    BiVariant() {
     178      flag = true;
     179      new(reinterpret_cast<First*>(data)) First();
     180    }
     181
     182    BiVariant(const First& first) {
     183      flag = true;
     184      new(reinterpret_cast<First*>(data)) First(first);
     185    }
     186
     187    BiVariant(const Second& second) {
     188      flag = false;
     189      new(reinterpret_cast<Second*>(data)) Second(second);
     190    }
     191
     192    BiVariant(const BiVariant& bivariant) {
     193      flag = bivariant.flag;
     194      if (flag) {
     195        new(reinterpret_cast<First*>(data)) First(bivariant.first());     
     196      } else {
     197        new(reinterpret_cast<Second*>(data)) Second(bivariant.second());     
     198      }
     199    }
     200
     201    ~BiVariant() {
     202      destroy();
     203    }
     204
     205    BiVariant& setFirst() {
     206      destroy();
     207      flag = true;
     208      new(reinterpret_cast<First*>(data)) First();   
     209      return *this;
     210    }
     211
     212    BiVariant& setFirst(const First& first) {
     213      destroy();
     214      flag = true;
     215      new(reinterpret_cast<First*>(data)) First(first);   
     216      return *this;
     217    }
     218
     219    BiVariant& setSecond() {
     220      destroy();
     221      flag = false;
     222      new(reinterpret_cast<Second*>(data)) Second();   
     223      return *this;
     224    }
     225
     226    BiVariant& setSecond(const Second& second) {
     227      destroy();
     228      flag = false;
     229      new(reinterpret_cast<Second*>(data)) Second(second);   
     230      return *this;
     231    }
     232
     233    BiVariant& operator=(const First& first) {
     234      return setFirst(first);
     235    }
     236
     237    BiVariant& operator=(const Second& second) {
     238      return setSecond(second);
     239    }
     240
     241
     242    BiVariant& operator=(const BiVariant& bivariant) {
     243      if (this == &bivariant) return *this;
     244      destroy();
     245      flag = bivariant.flag;
     246      if (flag) {
     247        new(reinterpret_cast<First*>(data)) First(bivariant.first());     
     248      } else {
     249        new(reinterpret_cast<Second*>(data)) Second(bivariant.second());     
     250      }
     251      return *this;
     252    }
     253
     254    First& first() {
     255      LEMON_ASSERT(flag, WrongStateError());
     256      return *reinterpret_cast<First*>(data);
     257    }
     258
     259    const First& first() const {
     260      LEMON_ASSERT(flag, WrongStateError());
     261      return *reinterpret_cast<const First*>(data);
     262    }
     263
     264    operator First&() { return first(); }
     265    operator const First&() const { return first(); }
     266
     267    Second& second() {
     268      LEMON_ASSERT(!flag, WrongStateError());
     269      return *reinterpret_cast<Second*>(data);
     270    }
     271
     272    const Second& second() const {
     273      LEMON_ASSERT(!flag, WrongStateError());
     274      return *reinterpret_cast<const Second*>(data);
     275    }
     276
     277    operator Second&() { return second(); }
     278    operator const Second&() const { return second(); }
     279
     280    bool firstState() const { return flag; }
     281    bool secondState() const { return !flag; }
     282
     283  private:
     284
     285    void destroy() {
     286      if (flag) {
     287        reinterpret_cast<First*>(data)->~First();
     288      } else {
     289        reinterpret_cast<Second*>(data)->~Second();
     290      }
     291    }
     292   
     293    char data[CTMax<sizeof(First), sizeof(Second)>::value];
     294    bool flag;
     295  };
    77296
    78297  template <typename T>
Note: See TracChangeset for help on using the changeset viewer.