1.1 --- a/lemon/bits/variant.h Fri Nov 03 14:24:44 2006 +0000
1.2 +++ b/lemon/bits/variant.h Fri Nov 03 15:21:52 2006 +0000
1.3 @@ -21,89 +21,36 @@
1.4
1.5 #include <lemon/error.h>
1.6
1.7 +/// \file
1.8 +/// \brief Variant types
1.9 +
1.10 namespace lemon {
1.11
1.12 - template <bool left, bool right>
1.13 - struct CTOr {
1.14 - static const bool value = true;
1.15 - };
1.16 + namespace _variant_bits {
1.17 +
1.18 + template <int left, int right>
1.19 + struct CTMax {
1.20 + static const int value = left < right ? right : left;
1.21 + };
1.22
1.23 - template <>
1.24 - struct CTOr<false, false> {
1.25 - static const bool value = false;
1.26 - };
1.27 + }
1.28
1.29 - template <bool left, bool right>
1.30 - struct CTAnd {
1.31 - static const bool value = false;
1.32 - };
1.33
1.34 - template <>
1.35 - struct CTAnd<true, true> {
1.36 - static const bool value = true;
1.37 - };
1.38 -
1.39 - template <int left, int right>
1.40 - struct CTEqual {
1.41 - static const bool value = false;
1.42 - };
1.43 -
1.44 - template <int val>
1.45 - struct CTEqual<val, val> {
1.46 - static const bool value = true;
1.47 - };
1.48 -
1.49 -
1.50 - template <int left, int right>
1.51 - struct CTLess {
1.52 - static const bool value = left < right;
1.53 - };
1.54 -
1.55 - template <int left>
1.56 - struct CTLess<left, 0> {
1.57 - static const bool value = false;
1.58 - };
1.59 -
1.60 - template <int right>
1.61 - struct CTLess<0, right> {
1.62 - static const bool value = true;
1.63 - };
1.64 -
1.65 - template <>
1.66 - struct CTLess<0, 0> {
1.67 - static const bool value = false;
1.68 - };
1.69 -
1.70 - template <>
1.71 - struct CTLess<1, 1> {
1.72 - static const bool value = false;
1.73 - };
1.74 -
1.75 - template <bool less, int left, int right>
1.76 - struct CTMaxImpl {
1.77 - static const int value = left;
1.78 - };
1.79 -
1.80 - template <int left, int right>
1.81 - struct CTMaxImpl<true, left, right> {
1.82 - static const int value = right;
1.83 - };
1.84 -
1.85 - template <int left, int right>
1.86 - struct CTMax {
1.87 - static const int value =
1.88 - CTMaxImpl<CTLess<left, right>::value, left, right>::value;
1.89 - };
1.90 -
1.91 -
1.92 - /// \brief Simple Variant type with two type
1.93 + /// \brief Simple Variant type for two types
1.94 ///
1.95 - /// Simple Variant type with two type
1.96 + /// Simple Variant type for two types. The Variant type is a type
1.97 + /// safe union. The C++ has strong limitations for using unions, by
1.98 + /// example we can not store type with non default constructor or
1.99 + /// destructor in an union. This class always knowns the current
1.100 + /// state of the variant and it cares for the proper construction
1.101 + /// and destruction.
1.102 template <typename _First, typename _Second>
1.103 class BiVariant {
1.104 public:
1.105
1.106 + /// \brief The \c First type.
1.107 typedef _First First;
1.108 + /// \brief The \c Second type.
1.109 typedef _Second Second;
1.110
1.111 struct WrongStateError : public lemon::LogicError {
1.112 @@ -113,21 +60,36 @@
1.113 }
1.114 };
1.115
1.116 + /// \brief Constructor
1.117 + ///
1.118 + /// This constructor initalizes to the default value of the \c First
1.119 + /// type.
1.120 BiVariant() {
1.121 flag = true;
1.122 new(reinterpret_cast<First*>(data)) First();
1.123 }
1.124
1.125 + /// \brief Constructor
1.126 + ///
1.127 + /// This constructor initalizes to the given value of the \c First
1.128 + /// type.
1.129 BiVariant(const First& first) {
1.130 flag = true;
1.131 new(reinterpret_cast<First*>(data)) First(first);
1.132 }
1.133
1.134 + /// \brief Constructor
1.135 + ///
1.136 + /// This constructor initalizes to the given value of the \c
1.137 + /// Second type.
1.138 BiVariant(const Second& second) {
1.139 flag = false;
1.140 new(reinterpret_cast<Second*>(data)) Second(second);
1.141 }
1.142
1.143 + /// \brief Copy constructor
1.144 + ///
1.145 + /// Copy constructor
1.146 BiVariant(const BiVariant& bivariant) {
1.147 flag = bivariant.flag;
1.148 if (flag) {
1.149 @@ -137,10 +99,17 @@
1.150 }
1.151 }
1.152
1.153 + /// \brief Destrcutor
1.154 + ///
1.155 + /// Destructor
1.156 ~BiVariant() {
1.157 destroy();
1.158 }
1.159
1.160 + /// \brief Set to the default value of the \c First type.
1.161 + ///
1.162 + /// This function sets the variant to the default value of the \c
1.163 + /// First type.
1.164 BiVariant& setFirst() {
1.165 destroy();
1.166 flag = true;
1.167 @@ -148,6 +117,10 @@
1.168 return *this;
1.169 }
1.170
1.171 + /// \brief Set to the given value of the \c First type.
1.172 + ///
1.173 + /// This function sets the variant to the given value of the \c
1.174 + /// First type.
1.175 BiVariant& setFirst(const First& first) {
1.176 destroy();
1.177 flag = true;
1.178 @@ -155,6 +128,10 @@
1.179 return *this;
1.180 }
1.181
1.182 + /// \brief Set to the default value of the \c Second type.
1.183 + ///
1.184 + /// This function sets the variant to the default value of the \c
1.185 + /// Second type.
1.186 BiVariant& setSecond() {
1.187 destroy();
1.188 flag = false;
1.189 @@ -162,6 +139,10 @@
1.190 return *this;
1.191 }
1.192
1.193 + /// \brief Set to the given value of the \c Second type.
1.194 + ///
1.195 + /// This function sets the variant to the given value of the \c
1.196 + /// Second type.
1.197 BiVariant& setSecond(const Second& second) {
1.198 destroy();
1.199 flag = false;
1.200 @@ -169,15 +150,17 @@
1.201 return *this;
1.202 }
1.203
1.204 + /// \brief Operator form of the \c setFirst()
1.205 BiVariant& operator=(const First& first) {
1.206 return setFirst(first);
1.207 }
1.208
1.209 + /// \brief Operator form of the \c setSecond()
1.210 BiVariant& operator=(const Second& second) {
1.211 return setSecond(second);
1.212 }
1.213
1.214 -
1.215 + /// \brief Assign operator
1.216 BiVariant& operator=(const BiVariant& bivariant) {
1.217 if (this == &bivariant) return *this;
1.218 destroy();
1.219 @@ -190,33 +173,60 @@
1.220 return *this;
1.221 }
1.222
1.223 + /// \brief Reference to the value
1.224 + ///
1.225 + /// Reference to the value of the \c First type.
1.226 + /// \pre The BiVariant should store value of \c First type.
1.227 First& first() {
1.228 LEMON_ASSERT(flag, WrongStateError());
1.229 return *reinterpret_cast<First*>(data);
1.230 }
1.231
1.232 + /// \brief Const reference to the value
1.233 + ///
1.234 + /// Const reference to the value of the \c First type.
1.235 + /// \pre The BiVariant should store value of \c First type.
1.236 const First& first() const {
1.237 LEMON_ASSERT(flag, WrongStateError());
1.238 return *reinterpret_cast<const First*>(data);
1.239 }
1.240
1.241 + /// \brief Operator form of the \c first()
1.242 operator First&() { return first(); }
1.243 + /// \brief Operator form of the const \c first()
1.244 operator const First&() const { return first(); }
1.245
1.246 + /// \brief Reference to the value
1.247 + ///
1.248 + /// Reference to the value of the \c Second type.
1.249 + /// \pre The BiVariant should store value of \c Second type.
1.250 Second& second() {
1.251 LEMON_ASSERT(!flag, WrongStateError());
1.252 return *reinterpret_cast<Second*>(data);
1.253 }
1.254
1.255 + /// \brief Const reference to the value
1.256 + ///
1.257 + /// Const reference to the value of the \c Second type.
1.258 + /// \pre The BiVariant should store value of \c Second type.
1.259 const Second& second() const {
1.260 LEMON_ASSERT(!flag, WrongStateError());
1.261 return *reinterpret_cast<const Second*>(data);
1.262 }
1.263
1.264 + /// \brief Operator form of the \c second()
1.265 operator Second&() { return second(); }
1.266 + /// \brief Operator form of the const \c second()
1.267 operator const Second&() const { return second(); }
1.268
1.269 + /// \brief %True when the variant is in the first state
1.270 + ///
1.271 + /// %True when the variant stores value of the \c First type.
1.272 bool firstState() const { return flag; }
1.273 +
1.274 + /// \brief %True when the variant is in the second state
1.275 + ///
1.276 + /// %True when the variant stores value of the \c Second type.
1.277 bool secondState() const { return !flag; }
1.278
1.279 private:
1.280 @@ -229,10 +239,269 @@
1.281 }
1.282 }
1.283
1.284 - char data[CTMax<sizeof(First), sizeof(Second)>::value];
1.285 + char data[_variant_bits::CTMax<sizeof(First), sizeof(Second)>::value];
1.286 bool flag;
1.287 };
1.288
1.289 + namespace _variant_bits {
1.290 +
1.291 + template <int _idx, typename _TypeMap>
1.292 + struct Memory {
1.293 +
1.294 + typedef typename _TypeMap::template Map<_idx>::Type Current;
1.295 +
1.296 + static void destroy(int index, char* place) {
1.297 + if (index == _idx) {
1.298 + reinterpret_cast<Current*>(place)->~Current();
1.299 + } else {
1.300 + Memory<_idx - 1, _TypeMap>::destroy(index, place);
1.301 + }
1.302 + }
1.303 +
1.304 + static void copy(int index, char* to, const char* from) {
1.305 + if (index == _idx) {
1.306 + new (reinterpret_cast<Current*>(to))
1.307 + Current(reinterpret_cast<const Current*>(from));
1.308 + } else {
1.309 + Memory<_idx - 1, _TypeMap>::copy(index, to, from);
1.310 + }
1.311 + }
1.312 +
1.313 + };
1.314 +
1.315 + template <typename _TypeMap>
1.316 + struct Memory<-1, _TypeMap> {
1.317 +
1.318 + static void destroy(int, char*) {
1.319 + LEMON_ASSERT(false, "Wrong Variant Index.");
1.320 + }
1.321 +
1.322 + static void copy(int, char*, const char*) {
1.323 + LEMON_ASSERT(false, "Wrong Variant Index.");
1.324 + }
1.325 + };
1.326 +
1.327 + template <int _idx, typename _TypeMap>
1.328 + struct Size {
1.329 + static const int value =
1.330 + CTMax<sizeof(typename _TypeMap::template Map<_idx>::Type),
1.331 + Size<_idx - 1, _TypeMap>::value>::value;
1.332 + };
1.333 +
1.334 + template <typename _TypeMap>
1.335 + struct Size<0, _TypeMap> {
1.336 + static const int value =
1.337 + sizeof(typename _TypeMap::template Map<0>::Type);
1.338 + };
1.339 +
1.340 + }
1.341 +
1.342 + /// \brief Variant type
1.343 + ///
1.344 + /// Simple Variant type. The Variant type is a type safe union. The
1.345 + /// C++ has strong limitations for using unions, by example we
1.346 + /// cannot store type with non default constructor or destructor in
1.347 + /// a union. This class always knowns the current state of the
1.348 + /// variant and it cares for the proper construction and
1.349 + /// destruction.
1.350 + ///
1.351 + /// \param _num The number of the types which can be stored in the
1.352 + /// variant type.
1.353 + /// \param _TypeMap This class describes the types of the Variant. The
1.354 + /// _TypeMap::Map<index>::Type should be a valid type for each index
1.355 + /// in the range {0, 1, ..., _num - 1}. The \c VariantTypeMap is helper
1.356 + /// class to define such type mappings up to 10 types.
1.357 + ///
1.358 + /// And the usage of the class:
1.359 + ///\code
1.360 + /// typedef Variant<3, VariantTypeMap<int, std::string, double> > MyVariant;
1.361 + /// MyVariant var;
1.362 + /// var.set<0>(12);
1.363 + /// std::cout << var.get<0>() << std::endl;
1.364 + /// var.set<1>("alpha");
1.365 + /// std::cout << var.get<1>() << std::endl;
1.366 + /// var.set<2>(0.75);
1.367 + /// std::cout << var.get<2>() << std::endl;
1.368 + ///\endcode
1.369 + ///
1.370 + /// The result of course:
1.371 + ///\code
1.372 + /// 12
1.373 + /// alpha
1.374 + /// 0.75
1.375 + ///\endcode
1.376 + template <int _num, typename _TypeMap>
1.377 + class Variant {
1.378 + public:
1.379 +
1.380 + static const int num = _num;
1.381 +
1.382 + typedef _TypeMap TypeMap;
1.383 +
1.384 + struct WrongStateError : public lemon::LogicError {
1.385 + public:
1.386 + virtual const char* what() const throw() {
1.387 + return "lemon::Variant::WrongStateError";
1.388 + }
1.389 + };
1.390 +
1.391 + /// \brief Constructor
1.392 + ///
1.393 + /// This constructor initalizes to the default value of the \c type
1.394 + /// with 0 index.
1.395 + Variant() {
1.396 + flag = 0;
1.397 + new(reinterpret_cast<typename TypeMap::template Map<0>::Type*>(data))
1.398 + typename TypeMap::template Map<0>::Type();
1.399 + }
1.400 +
1.401 +
1.402 + /// \brief Copy constructor
1.403 + ///
1.404 + /// Copy constructor
1.405 + Variant(const Variant& variant) {
1.406 + flag = variant.flag;
1.407 + _variant_bits::Memory<num - 1, TypeMap>::copy(flag, data, variant.data);
1.408 + }
1.409 +
1.410 + /// \brief Assign operator
1.411 + ///
1.412 + /// Assign operator
1.413 + Variant& operator=(const Variant& variant) {
1.414 + if (this == &variant) return *this;
1.415 + _variant_bits::Memory<num - 1, TypeMap>::
1.416 + destroy(flag, data);
1.417 + flag = variant.flag;
1.418 + _variant_bits::Memory<num - 1, TypeMap>::
1.419 + copy(flag, data, variant.data);
1.420 + return *this;
1.421 + }
1.422 +
1.423 + /// \brief Destrcutor
1.424 + ///
1.425 + /// Destructor
1.426 + ~Variant() {
1.427 + _variant_bits::Memory<num - 1, TypeMap>::destroy(flag, data);
1.428 + }
1.429 +
1.430 + /// \brief Set to the default value of the type with \c _idx index.
1.431 + ///
1.432 + /// This function sets the variant to the default value of the
1.433 + /// type with \c _idx index.
1.434 + template <int _idx>
1.435 + Variant& set() {
1.436 + _variant_bits::Memory<num - 1, TypeMap>::destroy(flag, data);
1.437 + flag = _idx;
1.438 + new(reinterpret_cast<typename TypeMap::template Map<_idx>::Type*>(data))
1.439 + typename TypeMap::template Map<_idx>::Type();
1.440 + return *this;
1.441 + }
1.442 +
1.443 + /// \brief Set to the given value of the type with \c _idx index.
1.444 + ///
1.445 + /// This function sets the variant to the given value of the type
1.446 + /// with \c _idx index.
1.447 + template <int _idx>
1.448 + Variant& set(const typename _TypeMap::template Map<_idx>::Type& init) {
1.449 + _variant_bits::Memory<num - 1, TypeMap>::destroy(flag, data);
1.450 + flag = _idx;
1.451 + new(reinterpret_cast<typename TypeMap::template Map<_idx>::Type*>(data))
1.452 + typename TypeMap::template Map<_idx>::Type(init);
1.453 + return *this;
1.454 + }
1.455 +
1.456 + /// \brief Gets the current value of the type with \c _idx index.
1.457 + ///
1.458 + /// Gets the current value of the type with \c _idx index.
1.459 + template <int _idx>
1.460 + const typename TypeMap::template Map<_idx>::Type& get() const {
1.461 + LEMON_ASSERT(_idx == flag, "Wrong Variant Index.");
1.462 + return *reinterpret_cast<const typename TypeMap::
1.463 + template Map<_idx>::Type*>(data);
1.464 + }
1.465 +
1.466 + /// \brief Gets the current value of the type with \c _idx index.
1.467 + ///
1.468 + /// Gets the current value of the type with \c _idx index.
1.469 + template <int _idx>
1.470 + typename _TypeMap::template Map<_idx>::Type& get() {
1.471 + LEMON_ASSERT(_idx == flag, "Wrong Variant Index.");
1.472 + return *reinterpret_cast<typename TypeMap::template Map<_idx>::Type*>
1.473 + (data);
1.474 + }
1.475 +
1.476 + /// \brief Returns the current state of the variant.
1.477 + ///
1.478 + /// Returns the current state of the variant.
1.479 + int state() const {
1.480 + return flag;
1.481 + }
1.482 +
1.483 + private:
1.484 +
1.485 + char data[_variant_bits::Size<num - 1, TypeMap>::value];
1.486 + int flag;
1.487 + };
1.488 +
1.489 + namespace _variant_bits {
1.490 +
1.491 + template <int _index, typename _List>
1.492 + struct Get {
1.493 + typedef typename Get<_index - 1, typename _List::Next>::Type Type;
1.494 + };
1.495 +
1.496 + template <typename _List>
1.497 + struct Get<0, _List> {
1.498 + typedef typename _List::Type Type;
1.499 + };
1.500 +
1.501 + struct List {};
1.502 +
1.503 + template <typename _Type, typename _List>
1.504 + struct Insert {
1.505 + typedef _List Next;
1.506 + typedef _Type Type;
1.507 + };
1.508 +
1.509 + template <int _idx, typename _T0, typename _T1, typename _T2,
1.510 + typename _T3, typename _T5, typename _T4, typename _T6,
1.511 + typename _T7, typename _T8, typename _T9>
1.512 + struct Mapper {
1.513 + typedef List L10;
1.514 + typedef Insert<_T9, L10> L9;
1.515 + typedef Insert<_T8, L9> L8;
1.516 + typedef Insert<_T7, L8> L7;
1.517 + typedef Insert<_T6, L7> L6;
1.518 + typedef Insert<_T5, L6> L5;
1.519 + typedef Insert<_T4, L5> L4;
1.520 + typedef Insert<_T3, L4> L3;
1.521 + typedef Insert<_T2, L3> L2;
1.522 + typedef Insert<_T1, L2> L1;
1.523 + typedef Insert<_T0, L1> L0;
1.524 + typedef typename Get<_idx, L0>::Type Type;
1.525 + };
1.526 +
1.527 + }
1.528 +
1.529 + /// \brief Helper class for Variant
1.530 + ///
1.531 + /// Helper class to define type mappings for Variant. This class
1.532 + /// converts the template parameters to be mappable by integer.
1.533 + /// \see Variant
1.534 + template <
1.535 + typename _T0,
1.536 + typename _T1 = void, typename _T2 = void, typename _T3 = void,
1.537 + typename _T5 = void, typename _T4 = void, typename _T6 = void,
1.538 + typename _T7 = void, typename _T8 = void, typename _T9 = void>
1.539 + struct VariantTypeMap {
1.540 + template <int _idx>
1.541 + struct Map {
1.542 + typedef typename _variant_bits::
1.543 + Mapper<_idx, _T0, _T1, _T2, _T3, _T4, _T5, _T6, _T7, _T8, _T9>::Type
1.544 + Type;
1.545 + };
1.546 + };
1.547 +
1.548 }
1.549
1.550