lemon/bits/variant.h
author deba
Wed, 18 Oct 2006 15:18:27 +0000
changeset 2255 4a9cc8c800ae
child 2292 38d985e82205
permissions -rw-r--r--
It have not been saved
deba@2177
     1
/* -*- C++ -*-
deba@2177
     2
 *
deba@2177
     3
 * This file is a part of LEMON, a generic C++ optimization library
deba@2177
     4
 *
deba@2177
     5
 * Copyright (C) 2003-2006
deba@2177
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
deba@2177
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
deba@2177
     8
 *
deba@2177
     9
 * Permission to use, modify and distribute this software is granted
deba@2177
    10
 * provided that this copyright notice appears in all copies. For
deba@2177
    11
 * precise terms see the accompanying LICENSE file.
deba@2177
    12
 *
deba@2177
    13
 * This software is provided "AS IS" with no warranty of any kind,
deba@2177
    14
 * express or implied, and with no claim as to its suitability for any
deba@2177
    15
 * purpose.
deba@2177
    16
 *
deba@2177
    17
 */
deba@2177
    18
deba@2177
    19
#ifndef LEMON_BITS_VARIANT_H
deba@2177
    20
#define LEMON_BITS_VARIANT_H
deba@2177
    21
deba@2177
    22
#include <lemon/error.h>
deba@2177
    23
deba@2177
    24
namespace lemon {
deba@2177
    25
deba@2177
    26
  template <bool left, bool right>
deba@2177
    27
  struct CTOr {
deba@2177
    28
    static const bool value = true;
deba@2177
    29
  };
deba@2177
    30
deba@2177
    31
  template <>
deba@2177
    32
  struct CTOr<false, false> {
deba@2177
    33
    static const bool value = false;
deba@2177
    34
  };
deba@2177
    35
deba@2177
    36
  template <bool left, bool right>
deba@2177
    37
  struct CTAnd {
deba@2177
    38
    static const bool value = false;
deba@2177
    39
  };
deba@2177
    40
deba@2177
    41
  template <>
deba@2177
    42
  struct CTAnd<true, true> {
deba@2177
    43
    static const bool value = true;
deba@2177
    44
  };
deba@2177
    45
deba@2177
    46
  template <int left, int right>
deba@2177
    47
  struct CTEqual {
deba@2177
    48
    static const bool value = false;
deba@2177
    49
  };
deba@2177
    50
deba@2177
    51
  template <int val>
deba@2177
    52
  struct CTEqual<val, val> {
deba@2177
    53
    static const bool value = true;
deba@2177
    54
  };
deba@2177
    55
deba@2177
    56
deba@2177
    57
  template <int left, int right>
deba@2177
    58
  struct CTLess {
deba@2177
    59
    static const bool value = left < right;
deba@2177
    60
  };
deba@2177
    61
deba@2177
    62
  template <int left>
deba@2177
    63
  struct CTLess<left, 0> {
deba@2177
    64
    static const bool value = false;
deba@2177
    65
  };
deba@2177
    66
deba@2177
    67
  template <int right>
deba@2177
    68
  struct CTLess<0, right> {
deba@2177
    69
    static const bool value = true;
deba@2177
    70
  };
deba@2177
    71
deba@2177
    72
  template <>
deba@2177
    73
  struct CTLess<0, 0> {
deba@2177
    74
    static const bool value = false;
deba@2177
    75
  };
deba@2177
    76
deba@2177
    77
  template <>
deba@2177
    78
  struct CTLess<1, 1> {
deba@2177
    79
    static const bool value = false;
deba@2177
    80
  };
deba@2177
    81
deba@2177
    82
  template <bool less, int left, int right>
deba@2177
    83
  struct CTMaxImpl {
deba@2177
    84
    static const int value = left;    
deba@2177
    85
  };
deba@2177
    86
deba@2177
    87
  template <int left, int right>
deba@2177
    88
  struct CTMaxImpl<true, left, right> {
deba@2177
    89
    static const int value = right;
deba@2177
    90
  };
deba@2177
    91
  
deba@2177
    92
  template <int left, int right>
deba@2177
    93
  struct CTMax {
deba@2177
    94
    static const int value = 
deba@2177
    95
    CTMaxImpl<CTLess<left, right>::value, left, right>::value;
deba@2177
    96
  };
deba@2177
    97
deba@2177
    98
deba@2177
    99
  /// \brief Simple Variant type with two type
deba@2177
   100
  ///
deba@2177
   101
  /// Simple Variant type with two type
deba@2177
   102
  template <typename _First, typename _Second>
deba@2177
   103
  class BiVariant {
deba@2177
   104
  public:
deba@2177
   105
deba@2177
   106
    typedef _First First;
deba@2177
   107
    typedef _Second Second;
deba@2177
   108
deba@2177
   109
    struct WrongStateError : public lemon::LogicError {
deba@2177
   110
    public:
deba@2177
   111
      virtual const char* what() const throw() {
deba@2177
   112
        return "lemon::BiVariant::WrongStateError";
deba@2177
   113
      }
deba@2177
   114
    };
deba@2177
   115
deba@2177
   116
    BiVariant() {
deba@2177
   117
      flag = true;
deba@2177
   118
      new(reinterpret_cast<First*>(data)) First();
deba@2177
   119
    }
deba@2177
   120
deba@2177
   121
    BiVariant(const First& first) {
deba@2177
   122
      flag = true;
deba@2177
   123
      new(reinterpret_cast<First*>(data)) First(first);
deba@2177
   124
    }
deba@2177
   125
deba@2177
   126
    BiVariant(const Second& second) {
deba@2177
   127
      flag = false;
deba@2177
   128
      new(reinterpret_cast<Second*>(data)) Second(second);
deba@2177
   129
    }
deba@2177
   130
deba@2177
   131
    BiVariant(const BiVariant& bivariant) {
deba@2177
   132
      flag = bivariant.flag;
deba@2177
   133
      if (flag) {
deba@2177
   134
        new(reinterpret_cast<First*>(data)) First(bivariant.first());      
deba@2177
   135
      } else {
deba@2177
   136
        new(reinterpret_cast<Second*>(data)) Second(bivariant.second());      
deba@2177
   137
      }
deba@2177
   138
    }
deba@2177
   139
deba@2177
   140
    ~BiVariant() {
deba@2177
   141
      destroy();
deba@2177
   142
    }
deba@2177
   143
deba@2177
   144
    BiVariant& setFirst() {
deba@2177
   145
      destroy();
deba@2177
   146
      flag = true;
deba@2177
   147
      new(reinterpret_cast<First*>(data)) First();   
deba@2177
   148
      return *this;
deba@2177
   149
    }
deba@2177
   150
deba@2177
   151
    BiVariant& setFirst(const First& first) {
deba@2177
   152
      destroy();
deba@2177
   153
      flag = true;
deba@2177
   154
      new(reinterpret_cast<First*>(data)) First(first);   
deba@2177
   155
      return *this;
deba@2177
   156
    }
deba@2177
   157
deba@2177
   158
    BiVariant& setSecond() {
deba@2177
   159
      destroy();
deba@2177
   160
      flag = false;
deba@2177
   161
      new(reinterpret_cast<Second*>(data)) Second();   
deba@2177
   162
      return *this;
deba@2177
   163
    }
deba@2177
   164
deba@2177
   165
    BiVariant& setSecond(const Second& second) {
deba@2177
   166
      destroy();
deba@2177
   167
      flag = false;
deba@2177
   168
      new(reinterpret_cast<Second*>(data)) Second(second);   
deba@2177
   169
      return *this;
deba@2177
   170
    }
deba@2177
   171
deba@2177
   172
    BiVariant& operator=(const First& first) {
deba@2177
   173
      return setFirst(first);
deba@2177
   174
    }
deba@2177
   175
deba@2177
   176
    BiVariant& operator=(const Second& second) {
deba@2177
   177
      return setSecond(second);
deba@2177
   178
    }
deba@2177
   179
deba@2177
   180
deba@2177
   181
    BiVariant& operator=(const BiVariant& bivariant) {
deba@2177
   182
      if (this == &bivariant) return *this;
deba@2177
   183
      destroy();
deba@2177
   184
      flag = bivariant.flag;
deba@2177
   185
      if (flag) {
deba@2177
   186
        new(reinterpret_cast<First*>(data)) First(bivariant.first());      
deba@2177
   187
      } else {
deba@2177
   188
        new(reinterpret_cast<Second*>(data)) Second(bivariant.second());      
deba@2177
   189
      }
deba@2177
   190
      return *this;
deba@2177
   191
    }
deba@2177
   192
deba@2177
   193
    First& first() {
deba@2177
   194
      LEMON_ASSERT(flag, WrongStateError());
deba@2177
   195
      return *reinterpret_cast<First*>(data); 
deba@2177
   196
    }
deba@2177
   197
deba@2177
   198
    const First& first() const { 
deba@2177
   199
      LEMON_ASSERT(flag, WrongStateError());
deba@2177
   200
      return *reinterpret_cast<const First*>(data); 
deba@2177
   201
    }
deba@2177
   202
deba@2177
   203
    operator First&() { return first(); }
deba@2177
   204
    operator const First&() const { return first(); }
deba@2177
   205
deba@2177
   206
    Second& second() { 
deba@2177
   207
      LEMON_ASSERT(!flag, WrongStateError());
deba@2177
   208
      return *reinterpret_cast<Second*>(data); 
deba@2177
   209
    }
deba@2177
   210
deba@2177
   211
    const Second& second() const { 
deba@2177
   212
      LEMON_ASSERT(!flag, WrongStateError());
deba@2177
   213
      return *reinterpret_cast<const Second*>(data); 
deba@2177
   214
    }
deba@2177
   215
deba@2177
   216
    operator Second&() { return second(); }
deba@2177
   217
    operator const Second&() const { return second(); }
deba@2177
   218
deba@2177
   219
    bool firstState() const { return flag; }
deba@2177
   220
    bool secondState() const { return !flag; }
deba@2177
   221
deba@2177
   222
  private:
deba@2177
   223
deba@2177
   224
    void destroy() {
deba@2177
   225
      if (flag) {
deba@2177
   226
        reinterpret_cast<First*>(data)->~First();
deba@2177
   227
      } else {
deba@2177
   228
        reinterpret_cast<Second*>(data)->~Second();
deba@2177
   229
      }
deba@2177
   230
    }
deba@2177
   231
    
deba@2177
   232
    char data[CTMax<sizeof(First), sizeof(Second)>::value];
deba@2177
   233
    bool flag;
deba@2177
   234
  };
deba@2177
   235
deba@2177
   236
}
deba@2177
   237
deba@2177
   238
deba@2177
   239
#endif