COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/bits/variant.h @ 2254:50cb2b90daa9

Last change on this file since 2254:50cb2b90daa9 was 2177:416a7030b7e3, checked in by Balazs Dezso, 13 years ago

BiVariant? moved to lemon/bits/variant.h

File size: 5.3 KB
Line 
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#ifndef LEMON_BITS_VARIANT_H
20#define LEMON_BITS_VARIANT_H
21
22#include <lemon/error.h>
23
24namespace lemon {
25
26  template <bool left, bool right>
27  struct CTOr {
28    static const bool value = true;
29  };
30
31  template <>
32  struct CTOr<false, false> {
33    static const bool value = false;
34  };
35
36  template <bool left, bool right>
37  struct CTAnd {
38    static const bool value = false;
39  };
40
41  template <>
42  struct CTAnd<true, true> {
43    static const bool value = true;
44  };
45
46  template <int left, int right>
47  struct CTEqual {
48    static const bool value = false;
49  };
50
51  template <int val>
52  struct CTEqual<val, val> {
53    static const bool value = true;
54  };
55
56
57  template <int left, int right>
58  struct CTLess {
59    static const bool value = left < right;
60  };
61
62  template <int left>
63  struct CTLess<left, 0> {
64    static const bool value = false;
65  };
66
67  template <int right>
68  struct CTLess<0, right> {
69    static const bool value = true;
70  };
71
72  template <>
73  struct CTLess<0, 0> {
74    static const bool value = false;
75  };
76
77  template <>
78  struct CTLess<1, 1> {
79    static const bool value = false;
80  };
81
82  template <bool less, int left, int right>
83  struct CTMaxImpl {
84    static const int value = left;   
85  };
86
87  template <int left, int right>
88  struct CTMaxImpl<true, left, right> {
89    static const int value = right;
90  };
91 
92  template <int left, int right>
93  struct CTMax {
94    static const int value =
95    CTMaxImpl<CTLess<left, right>::value, left, right>::value;
96  };
97
98
99  /// \brief Simple Variant type with two type
100  ///
101  /// Simple Variant type with two type
102  template <typename _First, typename _Second>
103  class BiVariant {
104  public:
105
106    typedef _First First;
107    typedef _Second Second;
108
109    struct WrongStateError : public lemon::LogicError {
110    public:
111      virtual const char* what() const throw() {
112        return "lemon::BiVariant::WrongStateError";
113      }
114    };
115
116    BiVariant() {
117      flag = true;
118      new(reinterpret_cast<First*>(data)) First();
119    }
120
121    BiVariant(const First& first) {
122      flag = true;
123      new(reinterpret_cast<First*>(data)) First(first);
124    }
125
126    BiVariant(const Second& second) {
127      flag = false;
128      new(reinterpret_cast<Second*>(data)) Second(second);
129    }
130
131    BiVariant(const BiVariant& bivariant) {
132      flag = bivariant.flag;
133      if (flag) {
134        new(reinterpret_cast<First*>(data)) First(bivariant.first());     
135      } else {
136        new(reinterpret_cast<Second*>(data)) Second(bivariant.second());     
137      }
138    }
139
140    ~BiVariant() {
141      destroy();
142    }
143
144    BiVariant& setFirst() {
145      destroy();
146      flag = true;
147      new(reinterpret_cast<First*>(data)) First();   
148      return *this;
149    }
150
151    BiVariant& setFirst(const First& first) {
152      destroy();
153      flag = true;
154      new(reinterpret_cast<First*>(data)) First(first);   
155      return *this;
156    }
157
158    BiVariant& setSecond() {
159      destroy();
160      flag = false;
161      new(reinterpret_cast<Second*>(data)) Second();   
162      return *this;
163    }
164
165    BiVariant& setSecond(const Second& second) {
166      destroy();
167      flag = false;
168      new(reinterpret_cast<Second*>(data)) Second(second);   
169      return *this;
170    }
171
172    BiVariant& operator=(const First& first) {
173      return setFirst(first);
174    }
175
176    BiVariant& operator=(const Second& second) {
177      return setSecond(second);
178    }
179
180
181    BiVariant& operator=(const BiVariant& bivariant) {
182      if (this == &bivariant) return *this;
183      destroy();
184      flag = bivariant.flag;
185      if (flag) {
186        new(reinterpret_cast<First*>(data)) First(bivariant.first());     
187      } else {
188        new(reinterpret_cast<Second*>(data)) Second(bivariant.second());     
189      }
190      return *this;
191    }
192
193    First& first() {
194      LEMON_ASSERT(flag, WrongStateError());
195      return *reinterpret_cast<First*>(data);
196    }
197
198    const First& first() const {
199      LEMON_ASSERT(flag, WrongStateError());
200      return *reinterpret_cast<const First*>(data);
201    }
202
203    operator First&() { return first(); }
204    operator const First&() const { return first(); }
205
206    Second& second() {
207      LEMON_ASSERT(!flag, WrongStateError());
208      return *reinterpret_cast<Second*>(data);
209    }
210
211    const Second& second() const {
212      LEMON_ASSERT(!flag, WrongStateError());
213      return *reinterpret_cast<const Second*>(data);
214    }
215
216    operator Second&() { return second(); }
217    operator const Second&() const { return second(); }
218
219    bool firstState() const { return flag; }
220    bool secondState() const { return !flag; }
221
222  private:
223
224    void destroy() {
225      if (flag) {
226        reinterpret_cast<First*>(data)->~First();
227      } else {
228        reinterpret_cast<Second*>(data)->~Second();
229      }
230    }
231   
232    char data[CTMax<sizeof(First), sizeof(Second)>::value];
233    bool flag;
234  };
235
236}
237
238
239#endif
Note: See TracBrowser for help on using the repository browser.