COIN-OR::LEMON - Graph Library

Changeset 2292:38d985e82205 in lemon-0.x for lemon/bits


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

General mapping based variant type

File:
1 edited

Legend:

Unmodified
Added
Removed
  • lemon/bits/variant.h

    r2177 r2292  
    2222#include <lemon/error.h>
    2323
     24/// \file
     25/// \brief Variant types
     26
    2427namespace lemon {
    2528
    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   };
     29  namespace _variant_bits {
    9130 
    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
     31    template <int left, int right>
     32    struct CTMax {
     33      static const int value = left < right ? right : left;
     34    };
     35
     36  }
     37
     38
     39  /// \brief Simple Variant type for two types
    10040  ///
    101   /// Simple Variant type with two type
     41  /// Simple Variant type for two types. The Variant type is a type
     42  /// safe union. The C++ has strong limitations for using unions, by
     43  /// example we can not store type with non default constructor or
     44  /// destructor in an union. This class always knowns the current
     45  /// state of the variant and it cares for the proper construction
     46  /// and destruction.
    10247  template <typename _First, typename _Second>
    10348  class BiVariant {
    10449  public:
    10550
     51    /// \brief The \c First type.
    10652    typedef _First First;
     53    /// \brief The \c Second type.
    10754    typedef _Second Second;
    10855
     
    11461    };
    11562
     63    /// \brief Constructor
     64    ///
     65    /// This constructor initalizes to the default value of the \c First
     66    /// type.
    11667    BiVariant() {
    11768      flag = true;
     
    11970    }
    12071
     72    /// \brief Constructor
     73    ///
     74    /// This constructor initalizes to the given value of the \c First
     75    /// type.
    12176    BiVariant(const First& first) {
    12277      flag = true;
     
    12479    }
    12580
     81    /// \brief Constructor
     82    ///
     83    /// This constructor initalizes to the given value of the \c
     84    /// Second type.
    12685    BiVariant(const Second& second) {
    12786      flag = false;
     
    12988    }
    13089
     90    /// \brief Copy constructor
     91    ///
     92    /// Copy constructor
    13193    BiVariant(const BiVariant& bivariant) {
    13294      flag = bivariant.flag;
     
    138100    }
    139101
     102    /// \brief Destrcutor
     103    ///
     104    /// Destructor
    140105    ~BiVariant() {
    141106      destroy();
    142107    }
    143108
     109    /// \brief Set to the default value of the \c First type.
     110    ///
     111    /// This function sets the variant to the default value of the \c
     112    /// First type.
    144113    BiVariant& setFirst() {
    145114      destroy();
     
    149118    }
    150119
     120    /// \brief Set to the given value of the \c First type.
     121    ///
     122    /// This function sets the variant to the given value of the \c
     123    /// First type.
    151124    BiVariant& setFirst(const First& first) {
    152125      destroy();
     
    156129    }
    157130
     131    /// \brief Set to the default value of the \c Second type.
     132    ///
     133    /// This function sets the variant to the default value of the \c
     134    /// Second type.
    158135    BiVariant& setSecond() {
    159136      destroy();
     
    163140    }
    164141
     142    /// \brief Set to the given value of the \c Second type.
     143    ///
     144    /// This function sets the variant to the given value of the \c
     145    /// Second type.
    165146    BiVariant& setSecond(const Second& second) {
    166147      destroy();
     
    170151    }
    171152
     153    /// \brief Operator form of the \c setFirst()
    172154    BiVariant& operator=(const First& first) {
    173155      return setFirst(first);
    174156    }
    175157
     158    /// \brief Operator form of the \c setSecond()
    176159    BiVariant& operator=(const Second& second) {
    177160      return setSecond(second);
    178161    }
    179162
    180 
     163    /// \brief Assign operator
    181164    BiVariant& operator=(const BiVariant& bivariant) {
    182165      if (this == &bivariant) return *this;
     
    191174    }
    192175
     176    /// \brief Reference to the value
     177    ///
     178    /// Reference to the value of the \c First type.
     179    /// \pre The BiVariant should store value of \c First type.
    193180    First& first() {
    194181      LEMON_ASSERT(flag, WrongStateError());
     
    196183    }
    197184
     185    /// \brief Const reference to the value
     186    ///
     187    /// Const reference to the value of the \c First type.
     188    /// \pre The BiVariant should store value of \c First type.
    198189    const First& first() const {
    199190      LEMON_ASSERT(flag, WrongStateError());
     
    201192    }
    202193
     194    /// \brief Operator form of the \c first()
    203195    operator First&() { return first(); }
     196    /// \brief Operator form of the const \c first()
    204197    operator const First&() const { return first(); }
    205198
     199    /// \brief Reference to the value
     200    ///
     201    /// Reference to the value of the \c Second type.
     202    /// \pre The BiVariant should store value of \c Second type.
    206203    Second& second() {
    207204      LEMON_ASSERT(!flag, WrongStateError());
     
    209206    }
    210207
     208    /// \brief Const reference to the value
     209    ///
     210    /// Const reference to the value of the \c Second type.
     211    /// \pre The BiVariant should store value of \c Second type.
    211212    const Second& second() const {
    212213      LEMON_ASSERT(!flag, WrongStateError());
     
    214215    }
    215216
     217    /// \brief Operator form of the \c second()
    216218    operator Second&() { return second(); }
     219    /// \brief Operator form of the const \c second()
    217220    operator const Second&() const { return second(); }
    218221
     222    /// \brief %True when the variant is in the first state
     223    ///
     224    /// %True when the variant stores value of the \c First type.
    219225    bool firstState() const { return flag; }
     226
     227    /// \brief %True when the variant is in the second state
     228    ///
     229    /// %True when the variant stores value of the \c Second type.
    220230    bool secondState() const { return !flag; }
    221231
     
    230240    }
    231241   
    232     char data[CTMax<sizeof(First), sizeof(Second)>::value];
     242    char data[_variant_bits::CTMax<sizeof(First), sizeof(Second)>::value];
    233243    bool flag;
    234244  };
    235245
     246  namespace _variant_bits {
     247   
     248    template <int _idx, typename _TypeMap>
     249    struct Memory {
     250
     251      typedef typename _TypeMap::template Map<_idx>::Type Current;
     252
     253      static void destroy(int index, char* place) {
     254        if (index == _idx) {
     255          reinterpret_cast<Current*>(place)->~Current();
     256        } else {
     257          Memory<_idx - 1, _TypeMap>::destroy(index, place);
     258        }
     259      }
     260
     261      static void copy(int index, char* to, const char* from) {
     262        if (index == _idx) {
     263          new (reinterpret_cast<Current*>(to))
     264            Current(reinterpret_cast<const Current*>(from));
     265        } else {
     266          Memory<_idx - 1, _TypeMap>::copy(index, to, from);
     267        }
     268      }
     269
     270    };
     271
     272    template <typename _TypeMap>
     273    struct Memory<-1, _TypeMap> {
     274
     275      static void destroy(int, char*) {
     276        LEMON_ASSERT(false, "Wrong Variant Index.");
     277      }
     278
     279      static void copy(int, char*, const char*) {
     280        LEMON_ASSERT(false, "Wrong Variant Index.");
     281      }
     282    };
     283
     284    template <int _idx, typename _TypeMap>
     285    struct Size {
     286      static const int value =
     287      CTMax<sizeof(typename _TypeMap::template Map<_idx>::Type),
     288            Size<_idx - 1, _TypeMap>::value>::value;
     289    };
     290
     291    template <typename _TypeMap>
     292    struct Size<0, _TypeMap> {
     293      static const int value =
     294      sizeof(typename _TypeMap::template Map<0>::Type);
     295    };
     296
     297  }
     298
     299  /// \brief Variant type
     300  ///
     301  /// Simple Variant type. The Variant type is a type safe union. The
     302  /// C++ has strong limitations for using unions, by example we
     303  /// cannot store type with non default constructor or destructor in
     304  /// a union. This class always knowns the current state of the
     305  /// variant and it cares for the proper construction and
     306  /// destruction.
     307  ///
     308  /// \param _num The number of the types which can be stored in the
     309  /// variant type.
     310  /// \param _TypeMap This class describes the types of the Variant. The
     311  /// _TypeMap::Map<index>::Type should be a valid type for each index
     312  /// in the range {0, 1, ..., _num - 1}. The \c VariantTypeMap is helper
     313  /// class to define such type mappings up to 10 types.
     314  ///
     315  /// And the usage of the class:
     316  ///\code
     317  /// typedef Variant<3, VariantTypeMap<int, std::string, double> > MyVariant;
     318  /// MyVariant var;
     319  /// var.set<0>(12);
     320  /// std::cout << var.get<0>() << std::endl;
     321  /// var.set<1>("alpha");
     322  /// std::cout << var.get<1>() << std::endl;
     323  /// var.set<2>(0.75);
     324  /// std::cout << var.get<2>() << std::endl;
     325  ///\endcode
     326  ///
     327  /// The result of course:
     328  ///\code
     329  /// 12
     330  /// alpha
     331  /// 0.75
     332  ///\endcode
     333  template <int _num, typename _TypeMap>
     334  class Variant {
     335  public:
     336
     337    static const int num = _num;
     338
     339    typedef _TypeMap TypeMap;
     340
     341    struct WrongStateError : public lemon::LogicError {
     342    public:
     343      virtual const char* what() const throw() {
     344        return "lemon::Variant::WrongStateError";
     345      }
     346    };
     347
     348    /// \brief Constructor
     349    ///
     350    /// This constructor initalizes to the default value of the \c type
     351    /// with 0 index.
     352    Variant() {
     353      flag = 0;
     354      new(reinterpret_cast<typename TypeMap::template Map<0>::Type*>(data))
     355        typename TypeMap::template Map<0>::Type();
     356    }
     357
     358
     359    /// \brief Copy constructor
     360    ///
     361    /// Copy constructor
     362    Variant(const Variant& variant) {
     363      flag = variant.flag;
     364      _variant_bits::Memory<num - 1, TypeMap>::copy(flag, data, variant.data);
     365    }
     366
     367    /// \brief Assign operator
     368    ///
     369    /// Assign operator
     370    Variant& operator=(const Variant& variant) {
     371      if (this == &variant) return *this;
     372      _variant_bits::Memory<num - 1, TypeMap>::
     373        destroy(flag, data);
     374      flag = variant.flag;
     375      _variant_bits::Memory<num - 1, TypeMap>::
     376        copy(flag, data, variant.data);
     377      return *this;
     378    }
     379
     380    /// \brief Destrcutor
     381    ///
     382    /// Destructor
     383    ~Variant() {
     384      _variant_bits::Memory<num - 1, TypeMap>::destroy(flag, data);
     385    }
     386
     387    /// \brief Set to the default value of the type with \c _idx index.
     388    ///
     389    /// This function sets the variant to the default value of the
     390    /// type with \c _idx index.
     391    template <int _idx>
     392    Variant& set() {
     393      _variant_bits::Memory<num - 1, TypeMap>::destroy(flag, data);
     394      flag = _idx;
     395      new(reinterpret_cast<typename TypeMap::template Map<_idx>::Type*>(data))
     396        typename TypeMap::template Map<_idx>::Type();
     397      return *this;
     398    }
     399
     400    /// \brief Set to the given value of the type with \c _idx index.
     401    ///
     402    /// This function sets the variant to the given value of the type
     403    /// with \c _idx index.
     404    template <int _idx>
     405    Variant& set(const typename _TypeMap::template Map<_idx>::Type& init) {
     406      _variant_bits::Memory<num - 1, TypeMap>::destroy(flag, data);
     407      flag = _idx;
     408      new(reinterpret_cast<typename TypeMap::template Map<_idx>::Type*>(data))
     409        typename TypeMap::template Map<_idx>::Type(init);
     410      return *this;
     411    }
     412
     413    /// \brief Gets the current value of the type with \c _idx index.
     414    ///
     415    /// Gets the current value of the type with \c _idx index.
     416    template <int _idx>
     417    const typename TypeMap::template Map<_idx>::Type& get() const {
     418      LEMON_ASSERT(_idx == flag, "Wrong Variant Index.");
     419      return *reinterpret_cast<const typename TypeMap::
     420        template Map<_idx>::Type*>(data);
     421    }
     422
     423    /// \brief Gets the current value of the type with \c _idx index.
     424    ///
     425    /// Gets the current value of the type with \c _idx index.
     426    template <int _idx>
     427    typename _TypeMap::template Map<_idx>::Type& get() {
     428      LEMON_ASSERT(_idx == flag, "Wrong Variant Index.");
     429      return *reinterpret_cast<typename TypeMap::template Map<_idx>::Type*>
     430        (data);
     431    }
     432
     433    /// \brief Returns the current state of the variant.
     434    ///
     435    /// Returns the current state of the variant.
     436    int state() const {
     437      return flag;
     438    }
     439
     440  private:
     441   
     442    char data[_variant_bits::Size<num - 1, TypeMap>::value];
     443    int flag;
     444  };
     445
     446  namespace _variant_bits {
     447
     448    template <int _index, typename _List>
     449    struct Get {
     450      typedef typename Get<_index - 1, typename _List::Next>::Type Type;
     451    };
     452
     453    template <typename _List>
     454    struct Get<0, _List> {
     455      typedef typename _List::Type Type;
     456    };
     457
     458    struct List {};
     459   
     460    template <typename _Type, typename _List>
     461    struct Insert {
     462      typedef _List Next;
     463      typedef _Type Type;
     464    };
     465
     466    template <int _idx, typename _T0, typename _T1, typename _T2,
     467              typename _T3, typename _T5, typename _T4, typename _T6,
     468              typename _T7, typename _T8, typename _T9>
     469    struct Mapper {
     470      typedef List L10;
     471      typedef Insert<_T9, L10> L9;
     472      typedef Insert<_T8, L9> L8;
     473      typedef Insert<_T7, L8> L7;
     474      typedef Insert<_T6, L7> L6;
     475      typedef Insert<_T5, L6> L5;
     476      typedef Insert<_T4, L5> L4;
     477      typedef Insert<_T3, L4> L3;
     478      typedef Insert<_T2, L3> L2;
     479      typedef Insert<_T1, L2> L1;
     480      typedef Insert<_T0, L1> L0;
     481      typedef typename Get<_idx, L0>::Type Type;
     482    };
     483   
     484  }
     485
     486  /// \brief Helper class for Variant
     487  ///
     488  /// Helper class to define type mappings for Variant. This class
     489  /// converts the template parameters to be mappable by integer.
     490  /// \see Variant
     491  template <
     492    typename _T0,
     493    typename _T1 = void, typename _T2 = void, typename _T3 = void,
     494    typename _T5 = void, typename _T4 = void, typename _T6 = void,
     495    typename _T7 = void, typename _T8 = void, typename _T9 = void>
     496  struct VariantTypeMap {
     497    template <int _idx>
     498    struct Map {
     499      typedef typename _variant_bits::
     500      Mapper<_idx, _T0, _T1, _T2, _T3, _T4, _T5, _T6, _T7, _T8, _T9>::Type
     501      Type;
     502    };
     503  };
     504 
    236505}
    237506
Note: See TracChangeset for help on using the changeset viewer.