lemon/bits/variant.h
author deba
Tue, 17 Oct 2006 10:50:57 +0000
changeset 2247 269a0dcee70b
child 2292 38d985e82205
permissions -rw-r--r--
Update the Path concept
Concept check for paths

DirPath renamed to Path
The interface updated to the new lemon interface
Make difference between the empty path and the path from one node
Builder interface have not been changed
// I wanted but there was not accordance about it

UPath is removed
It was a buggy implementation, it could not iterate on the
nodes in the right order
Right way to use undirected paths => path of edges in undirected graphs

The tests have been modified to the current implementation
     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 
    24 namespace 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