General mapping based variant type
authordeba
Fri, 03 Nov 2006 15:21:52 +0000
changeset 229238d985e82205
parent 2291 fbc4af1f9378
child 2293 1ee6e8788cc7
General mapping based variant type
lemon/bits/variant.h
     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