lemon/bits/variant.h
author Peter Kovacs <kpeter@inf.elte.hu>
Fri, 12 Dec 2008 21:46:08 +0100
changeset 452 9dfaf6efc36f
parent 451 09e416d35896
child 463 88ed40ad0d4f
permissions -rw-r--r--
Hide all docs in variant.h (#196)
deba@432
     1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
deba@430
     2
 *
deba@432
     3
 * This file is a part of LEMON, a generic C++ optimization library.
deba@430
     4
 *
deba@430
     5
 * Copyright (C) 2003-2008
deba@430
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
deba@430
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
deba@430
     8
 *
deba@430
     9
 * Permission to use, modify and distribute this software is granted
deba@430
    10
 * provided that this copyright notice appears in all copies. For
deba@430
    11
 * precise terms see the accompanying LICENSE file.
deba@430
    12
 *
deba@430
    13
 * This software is provided "AS IS" with no warranty of any kind,
deba@430
    14
 * express or implied, and with no claim as to its suitability for any
deba@430
    15
 * purpose.
deba@430
    16
 *
deba@430
    17
 */
deba@430
    18
deba@430
    19
#ifndef LEMON_BITS_VARIANT_H
deba@430
    20
#define LEMON_BITS_VARIANT_H
deba@430
    21
deba@430
    22
#include <lemon/assert.h>
deba@430
    23
kpeter@452
    24
// \file
kpeter@452
    25
// \brief Variant types
deba@430
    26
deba@430
    27
namespace lemon {
deba@430
    28
deba@430
    29
  namespace _variant_bits {
deba@432
    30
deba@430
    31
    template <int left, int right>
deba@430
    32
    struct CTMax {
deba@430
    33
      static const int value = left < right ? right : left;
deba@430
    34
    };
deba@430
    35
deba@430
    36
  }
deba@430
    37
deba@430
    38
kpeter@452
    39
  // \brief Simple Variant type for two types
kpeter@452
    40
  //
kpeter@452
    41
  // Simple Variant type for two types. The Variant type is a type-safe
kpeter@452
    42
  // union. C++ has strong limitations for using unions, for
kpeter@452
    43
  // example you cannot store a type with non-default constructor or
kpeter@452
    44
  // destructor in a union. This class always knowns the current
kpeter@452
    45
  // state of the variant and it cares for the proper construction
kpeter@452
    46
  // and destruction.
deba@430
    47
  template <typename _First, typename _Second>
deba@430
    48
  class BiVariant {
deba@430
    49
  public:
deba@430
    50
kpeter@452
    51
    // \brief The \c First type.
deba@430
    52
    typedef _First First;
kpeter@452
    53
    // \brief The \c Second type.
deba@430
    54
    typedef _Second Second;
deba@430
    55
kpeter@452
    56
    // \brief Constructor
kpeter@452
    57
    //
kpeter@452
    58
    // This constructor initalizes to the default value of the \c First
kpeter@452
    59
    // type.
deba@430
    60
    BiVariant() {
deba@430
    61
      flag = true;
deba@430
    62
      new(reinterpret_cast<First*>(data)) First();
deba@430
    63
    }
deba@430
    64
kpeter@452
    65
    // \brief Constructor
kpeter@452
    66
    //
kpeter@452
    67
    // This constructor initalizes to the given value of the \c First
kpeter@452
    68
    // type.
deba@430
    69
    BiVariant(const First& f) {
deba@430
    70
      flag = true;
deba@430
    71
      new(reinterpret_cast<First*>(data)) First(f);
deba@430
    72
    }
deba@430
    73
kpeter@452
    74
    // \brief Constructor
kpeter@452
    75
    //
kpeter@452
    76
    // This constructor initalizes to the given value of the \c
kpeter@452
    77
    // Second type.
deba@430
    78
    BiVariant(const Second& s) {
deba@430
    79
      flag = false;
deba@430
    80
      new(reinterpret_cast<Second*>(data)) Second(s);
deba@430
    81
    }
deba@430
    82
kpeter@452
    83
    // \brief Copy constructor
kpeter@452
    84
    //
kpeter@452
    85
    // Copy constructor
deba@430
    86
    BiVariant(const BiVariant& bivariant) {
deba@430
    87
      flag = bivariant.flag;
deba@430
    88
      if (flag) {
deba@432
    89
        new(reinterpret_cast<First*>(data)) First(bivariant.first());
deba@430
    90
      } else {
deba@432
    91
        new(reinterpret_cast<Second*>(data)) Second(bivariant.second());
deba@430
    92
      }
deba@430
    93
    }
deba@430
    94
kpeter@452
    95
    // \brief Destrcutor
kpeter@452
    96
    //
kpeter@452
    97
    // Destructor
deba@430
    98
    ~BiVariant() {
deba@430
    99
      destroy();
deba@430
   100
    }
deba@430
   101
kpeter@452
   102
    // \brief Set to the default value of the \c First type.
kpeter@452
   103
    //
kpeter@452
   104
    // This function sets the variant to the default value of the \c
kpeter@452
   105
    // First type.
deba@430
   106
    BiVariant& setFirst() {
deba@430
   107
      destroy();
deba@430
   108
      flag = true;
deba@432
   109
      new(reinterpret_cast<First*>(data)) First();
deba@430
   110
      return *this;
deba@430
   111
    }
deba@430
   112
kpeter@452
   113
    // \brief Set to the given value of the \c First type.
kpeter@452
   114
    //
kpeter@452
   115
    // This function sets the variant to the given value of the \c
kpeter@452
   116
    // First type.
deba@430
   117
    BiVariant& setFirst(const First& f) {
deba@430
   118
      destroy();
deba@430
   119
      flag = true;
deba@432
   120
      new(reinterpret_cast<First*>(data)) First(f);
deba@430
   121
      return *this;
deba@430
   122
    }
deba@430
   123
kpeter@452
   124
    // \brief Set to the default value of the \c Second type.
kpeter@452
   125
    //
kpeter@452
   126
    // This function sets the variant to the default value of the \c
kpeter@452
   127
    // Second type.
deba@430
   128
    BiVariant& setSecond() {
deba@430
   129
      destroy();
deba@430
   130
      flag = false;
deba@432
   131
      new(reinterpret_cast<Second*>(data)) Second();
deba@430
   132
      return *this;
deba@430
   133
    }
deba@430
   134
kpeter@452
   135
    // \brief Set to the given value of the \c Second type.
kpeter@452
   136
    //
kpeter@452
   137
    // This function sets the variant to the given value of the \c
kpeter@452
   138
    // Second type.
deba@430
   139
    BiVariant& setSecond(const Second& s) {
deba@430
   140
      destroy();
deba@430
   141
      flag = false;
deba@432
   142
      new(reinterpret_cast<Second*>(data)) Second(s);
deba@430
   143
      return *this;
deba@430
   144
    }
deba@430
   145
kpeter@452
   146
    // \brief Operator form of the \c setFirst()
deba@430
   147
    BiVariant& operator=(const First& f) {
deba@430
   148
      return setFirst(f);
deba@430
   149
    }
deba@430
   150
kpeter@452
   151
    // \brief Operator form of the \c setSecond()
deba@430
   152
    BiVariant& operator=(const Second& s) {
deba@430
   153
      return setSecond(s);
deba@430
   154
    }
deba@430
   155
kpeter@452
   156
    // \brief Assign operator
deba@430
   157
    BiVariant& operator=(const BiVariant& bivariant) {
deba@430
   158
      if (this == &bivariant) return *this;
deba@430
   159
      destroy();
deba@430
   160
      flag = bivariant.flag;
deba@430
   161
      if (flag) {
deba@432
   162
        new(reinterpret_cast<First*>(data)) First(bivariant.first());
deba@430
   163
      } else {
deba@432
   164
        new(reinterpret_cast<Second*>(data)) Second(bivariant.second());
deba@430
   165
      }
deba@430
   166
      return *this;
deba@430
   167
    }
deba@430
   168
kpeter@452
   169
    // \brief Reference to the value
kpeter@452
   170
    //
kpeter@452
   171
    // Reference to the value of the \c First type.
kpeter@452
   172
    // \pre The BiVariant should store value of \c First type.
deba@430
   173
    First& first() {
deba@430
   174
      LEMON_DEBUG(flag, "Variant wrong state");
kpeter@452
   175
      return *reinterpret_cast<First*>(data);
deba@430
   176
    }
deba@430
   177
kpeter@452
   178
    // \brief Const reference to the value
kpeter@452
   179
    //
kpeter@452
   180
    // Const reference to the value of the \c First type.
kpeter@452
   181
    // \pre The BiVariant should store value of \c First type.
kpeter@452
   182
    const First& first() const {
deba@430
   183
      LEMON_DEBUG(flag, "Variant wrong state");
kpeter@452
   184
      return *reinterpret_cast<const First*>(data);
deba@430
   185
    }
deba@430
   186
kpeter@452
   187
    // \brief Operator form of the \c first()
deba@430
   188
    operator First&() { return first(); }
kpeter@452
   189
    // \brief Operator form of the const \c first()
deba@430
   190
    operator const First&() const { return first(); }
deba@430
   191
kpeter@452
   192
    // \brief Reference to the value
kpeter@452
   193
    //
kpeter@452
   194
    // Reference to the value of the \c Second type.
kpeter@452
   195
    // \pre The BiVariant should store value of \c Second type.
kpeter@452
   196
    Second& second() {
deba@430
   197
      LEMON_DEBUG(!flag, "Variant wrong state");
kpeter@452
   198
      return *reinterpret_cast<Second*>(data);
deba@430
   199
    }
deba@430
   200
kpeter@452
   201
    // \brief Const reference to the value
kpeter@452
   202
    //
kpeter@452
   203
    // Const reference to the value of the \c Second type.
kpeter@452
   204
    // \pre The BiVariant should store value of \c Second type.
kpeter@452
   205
    const Second& second() const {
deba@430
   206
      LEMON_DEBUG(!flag, "Variant wrong state");
kpeter@452
   207
      return *reinterpret_cast<const Second*>(data);
deba@430
   208
    }
deba@430
   209
kpeter@452
   210
    // \brief Operator form of the \c second()
deba@430
   211
    operator Second&() { return second(); }
kpeter@452
   212
    // \brief Operator form of the const \c second()
deba@430
   213
    operator const Second&() const { return second(); }
deba@430
   214
kpeter@452
   215
    // \brief %True when the variant is in the first state
kpeter@452
   216
    //
kpeter@452
   217
    // %True when the variant stores value of the \c First type.
deba@430
   218
    bool firstState() const { return flag; }
deba@430
   219
kpeter@452
   220
    // \brief %True when the variant is in the second state
kpeter@452
   221
    //
kpeter@452
   222
    // %True when the variant stores value of the \c Second type.
deba@430
   223
    bool secondState() const { return !flag; }
deba@430
   224
deba@430
   225
  private:
deba@430
   226
deba@430
   227
    void destroy() {
deba@430
   228
      if (flag) {
deba@430
   229
        reinterpret_cast<First*>(data)->~First();
deba@430
   230
      } else {
deba@430
   231
        reinterpret_cast<Second*>(data)->~Second();
deba@430
   232
      }
deba@430
   233
    }
deba@432
   234
deba@430
   235
    char data[_variant_bits::CTMax<sizeof(First), sizeof(Second)>::value];
deba@430
   236
    bool flag;
deba@430
   237
  };
deba@430
   238
deba@430
   239
  namespace _variant_bits {
deba@432
   240
deba@430
   241
    template <int _idx, typename _TypeMap>
deba@430
   242
    struct Memory {
deba@430
   243
deba@430
   244
      typedef typename _TypeMap::template Map<_idx>::Type Current;
deba@430
   245
deba@430
   246
      static void destroy(int index, char* place) {
deba@430
   247
        if (index == _idx) {
deba@430
   248
          reinterpret_cast<Current*>(place)->~Current();
deba@430
   249
        } else {
deba@430
   250
          Memory<_idx - 1, _TypeMap>::destroy(index, place);
deba@430
   251
        }
deba@430
   252
      }
deba@430
   253
deba@430
   254
      static void copy(int index, char* to, const char* from) {
deba@430
   255
        if (index == _idx) {
deba@430
   256
          new (reinterpret_cast<Current*>(to))
deba@430
   257
            Current(reinterpret_cast<const Current*>(from));
deba@430
   258
        } else {
deba@430
   259
          Memory<_idx - 1, _TypeMap>::copy(index, to, from);
deba@430
   260
        }
deba@430
   261
      }
deba@430
   262
deba@430
   263
    };
deba@430
   264
deba@430
   265
    template <typename _TypeMap>
deba@430
   266
    struct Memory<-1, _TypeMap> {
deba@430
   267
deba@430
   268
      static void destroy(int, char*) {
deba@430
   269
        LEMON_DEBUG(false, "Variant wrong index.");
deba@430
   270
      }
deba@430
   271
deba@430
   272
      static void copy(int, char*, const char*) {
deba@430
   273
        LEMON_DEBUG(false, "Variant wrong index.");
deba@430
   274
      }
deba@430
   275
    };
deba@430
   276
deba@430
   277
    template <int _idx, typename _TypeMap>
deba@430
   278
    struct Size {
deba@432
   279
      static const int value =
deba@432
   280
      CTMax<sizeof(typename _TypeMap::template Map<_idx>::Type),
deba@430
   281
            Size<_idx - 1, _TypeMap>::value>::value;
deba@430
   282
    };
deba@430
   283
deba@430
   284
    template <typename _TypeMap>
deba@430
   285
    struct Size<0, _TypeMap> {
deba@432
   286
      static const int value =
deba@430
   287
      sizeof(typename _TypeMap::template Map<0>::Type);
deba@430
   288
    };
deba@430
   289
deba@430
   290
  }
deba@430
   291
kpeter@452
   292
  // \brief Variant type
kpeter@452
   293
  //
kpeter@452
   294
  // Simple Variant type. The Variant type is a type-safe union.
kpeter@452
   295
  // C++ has strong limitations for using unions, for example you
kpeter@452
   296
  // cannot store type with non-default constructor or destructor in
kpeter@452
   297
  // a union. This class always knowns the current state of the
kpeter@452
   298
  // variant and it cares for the proper construction and
kpeter@452
   299
  // destruction.
kpeter@452
   300
  //
kpeter@452
   301
  // \param _num The number of the types which can be stored in the
kpeter@452
   302
  // variant type.
kpeter@452
   303
  // \param _TypeMap This class describes the types of the Variant. The
kpeter@452
   304
  // _TypeMap::Map<index>::Type should be a valid type for each index
kpeter@452
   305
  // in the range {0, 1, ..., _num - 1}. The \c VariantTypeMap is helper
kpeter@452
   306
  // class to define such type mappings up to 10 types.
kpeter@452
   307
  //
kpeter@452
   308
  // And the usage of the class:
kpeter@452
   309
  //\code
kpeter@452
   310
  // typedef Variant<3, VariantTypeMap<int, std::string, double> > MyVariant;
kpeter@452
   311
  // MyVariant var;
kpeter@452
   312
  // var.set<0>(12);
kpeter@452
   313
  // std::cout << var.get<0>() << std::endl;
kpeter@452
   314
  // var.set<1>("alpha");
kpeter@452
   315
  // std::cout << var.get<1>() << std::endl;
kpeter@452
   316
  // var.set<2>(0.75);
kpeter@452
   317
  // std::cout << var.get<2>() << std::endl;
kpeter@452
   318
  //\endcode
kpeter@452
   319
  //
kpeter@452
   320
  // The result of course:
kpeter@452
   321
  //\code
kpeter@452
   322
  // 12
kpeter@452
   323
  // alpha
kpeter@452
   324
  // 0.75
kpeter@452
   325
  //\endcode
deba@430
   326
  template <int _num, typename _TypeMap>
deba@430
   327
  class Variant {
deba@430
   328
  public:
deba@430
   329
deba@430
   330
    static const int num = _num;
deba@430
   331
deba@430
   332
    typedef _TypeMap TypeMap;
deba@430
   333
kpeter@452
   334
    // \brief Constructor
kpeter@452
   335
    //
kpeter@452
   336
    // This constructor initalizes to the default value of the \c type
kpeter@452
   337
    // with 0 index.
deba@430
   338
    Variant() {
deba@430
   339
      flag = 0;
deba@432
   340
      new(reinterpret_cast<typename TypeMap::template Map<0>::Type*>(data))
deba@430
   341
        typename TypeMap::template Map<0>::Type();
deba@430
   342
    }
deba@430
   343
deba@430
   344
kpeter@452
   345
    // \brief Copy constructor
kpeter@452
   346
    //
kpeter@452
   347
    // Copy constructor
deba@430
   348
    Variant(const Variant& variant) {
deba@430
   349
      flag = variant.flag;
deba@430
   350
      _variant_bits::Memory<num - 1, TypeMap>::copy(flag, data, variant.data);
deba@430
   351
    }
deba@430
   352
kpeter@452
   353
    // \brief Assign operator
kpeter@452
   354
    //
kpeter@452
   355
    // Assign operator
deba@430
   356
    Variant& operator=(const Variant& variant) {
deba@430
   357
      if (this == &variant) return *this;
deba@430
   358
      _variant_bits::Memory<num - 1, TypeMap>::
deba@430
   359
        destroy(flag, data);
deba@430
   360
      flag = variant.flag;
deba@430
   361
      _variant_bits::Memory<num - 1, TypeMap>::
deba@430
   362
        copy(flag, data, variant.data);
deba@430
   363
      return *this;
deba@430
   364
    }
deba@430
   365
kpeter@452
   366
    // \brief Destrcutor
kpeter@452
   367
    //
kpeter@452
   368
    // Destructor
deba@430
   369
    ~Variant() {
deba@430
   370
      _variant_bits::Memory<num - 1, TypeMap>::destroy(flag, data);
deba@430
   371
    }
deba@430
   372
kpeter@452
   373
    // \brief Set to the default value of the type with \c _idx index.
kpeter@452
   374
    //
kpeter@452
   375
    // This function sets the variant to the default value of the
kpeter@452
   376
    // type with \c _idx index.
deba@430
   377
    template <int _idx>
deba@430
   378
    Variant& set() {
deba@430
   379
      _variant_bits::Memory<num - 1, TypeMap>::destroy(flag, data);
deba@430
   380
      flag = _idx;
deba@432
   381
      new(reinterpret_cast<typename TypeMap::template Map<_idx>::Type*>(data))
deba@430
   382
        typename TypeMap::template Map<_idx>::Type();
deba@430
   383
      return *this;
deba@430
   384
    }
deba@430
   385
kpeter@452
   386
    // \brief Set to the given value of the type with \c _idx index.
kpeter@452
   387
    //
kpeter@452
   388
    // This function sets the variant to the given value of the type
kpeter@452
   389
    // with \c _idx index.
deba@430
   390
    template <int _idx>
deba@430
   391
    Variant& set(const typename _TypeMap::template Map<_idx>::Type& init) {
deba@430
   392
      _variant_bits::Memory<num - 1, TypeMap>::destroy(flag, data);
deba@430
   393
      flag = _idx;
deba@432
   394
      new(reinterpret_cast<typename TypeMap::template Map<_idx>::Type*>(data))
deba@430
   395
        typename TypeMap::template Map<_idx>::Type(init);
deba@430
   396
      return *this;
deba@430
   397
    }
deba@430
   398
kpeter@452
   399
    // \brief Gets the current value of the type with \c _idx index.
kpeter@452
   400
    //
kpeter@452
   401
    // Gets the current value of the type with \c _idx index.
deba@430
   402
    template <int _idx>
deba@430
   403
    const typename TypeMap::template Map<_idx>::Type& get() const {
deba@430
   404
      LEMON_DEBUG(_idx == flag, "Variant wrong index");
deba@430
   405
      return *reinterpret_cast<const typename TypeMap::
deba@432
   406
        template Map<_idx>::Type*>(data);
deba@430
   407
    }
deba@430
   408
kpeter@452
   409
    // \brief Gets the current value of the type with \c _idx index.
kpeter@452
   410
    //
kpeter@452
   411
    // Gets the current value of the type with \c _idx index.
deba@430
   412
    template <int _idx>
deba@430
   413
    typename _TypeMap::template Map<_idx>::Type& get() {
deba@430
   414
      LEMON_DEBUG(_idx == flag, "Variant wrong index");
deba@430
   415
      return *reinterpret_cast<typename TypeMap::template Map<_idx>::Type*>
deba@432
   416
        (data);
deba@430
   417
    }
deba@430
   418
kpeter@452
   419
    // \brief Returns the current state of the variant.
kpeter@452
   420
    //
kpeter@452
   421
    // Returns the current state of the variant.
deba@430
   422
    int state() const {
deba@430
   423
      return flag;
deba@430
   424
    }
deba@430
   425
deba@430
   426
  private:
deba@432
   427
deba@430
   428
    char data[_variant_bits::Size<num - 1, TypeMap>::value];
deba@430
   429
    int flag;
deba@430
   430
  };
deba@430
   431
deba@430
   432
  namespace _variant_bits {
deba@430
   433
deba@430
   434
    template <int _index, typename _List>
deba@430
   435
    struct Get {
deba@430
   436
      typedef typename Get<_index - 1, typename _List::Next>::Type Type;
deba@430
   437
    };
deba@430
   438
deba@430
   439
    template <typename _List>
deba@430
   440
    struct Get<0, _List> {
deba@430
   441
      typedef typename _List::Type Type;
deba@430
   442
    };
deba@430
   443
deba@430
   444
    struct List {};
deba@432
   445
deba@430
   446
    template <typename _Type, typename _List>
deba@430
   447
    struct Insert {
deba@430
   448
      typedef _List Next;
deba@430
   449
      typedef _Type Type;
deba@430
   450
    };
deba@430
   451
deba@432
   452
    template <int _idx, typename _T0, typename _T1, typename _T2,
kpeter@451
   453
              typename _T3, typename _T4, typename _T5, typename _T6,
deba@430
   454
              typename _T7, typename _T8, typename _T9>
deba@430
   455
    struct Mapper {
deba@430
   456
      typedef List L10;
deba@430
   457
      typedef Insert<_T9, L10> L9;
deba@430
   458
      typedef Insert<_T8, L9> L8;
deba@430
   459
      typedef Insert<_T7, L8> L7;
deba@430
   460
      typedef Insert<_T6, L7> L6;
deba@430
   461
      typedef Insert<_T5, L6> L5;
deba@430
   462
      typedef Insert<_T4, L5> L4;
deba@430
   463
      typedef Insert<_T3, L4> L3;
deba@430
   464
      typedef Insert<_T2, L3> L2;
deba@430
   465
      typedef Insert<_T1, L2> L1;
deba@430
   466
      typedef Insert<_T0, L1> L0;
deba@430
   467
      typedef typename Get<_idx, L0>::Type Type;
deba@430
   468
    };
deba@432
   469
deba@430
   470
  }
deba@430
   471
kpeter@452
   472
  // \brief Helper class for Variant
kpeter@452
   473
  //
kpeter@452
   474
  // Helper class to define type mappings for Variant. This class
kpeter@452
   475
  // converts the template parameters to be mappable by integer.
kpeter@452
   476
  // \see Variant
deba@430
   477
  template <
deba@432
   478
    typename _T0,
deba@430
   479
    typename _T1 = void, typename _T2 = void, typename _T3 = void,
kpeter@451
   480
    typename _T4 = void, typename _T5 = void, typename _T6 = void,
deba@430
   481
    typename _T7 = void, typename _T8 = void, typename _T9 = void>
deba@430
   482
  struct VariantTypeMap {
deba@430
   483
    template <int _idx>
deba@430
   484
    struct Map {
deba@430
   485
      typedef typename _variant_bits::
deba@430
   486
      Mapper<_idx, _T0, _T1, _T2, _T3, _T4, _T5, _T6, _T7, _T8, _T9>::Type
deba@430
   487
      Type;
deba@430
   488
    };
deba@430
   489
  };
deba@432
   490
deba@430
   491
}
deba@430
   492
deba@430
   493
deba@430
   494
#endif