Vaucanson 1.4
unique.hxx
00001 // unique.hxx: this file is part of the Vaucanson project.
00002 //
00003 // Vaucanson, a generic library for finite state machines.
00004 //
00005 // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 The Vaucanson Group.
00006 //
00007 // This program is free software; you can redistribute it and/or
00008 // modify it under the terms of the GNU General Public License
00009 // as published by the Free Software Foundation; either version 2
00010 // of the License, or (at your option) any later version.
00011 //
00012 // The complete GNU General Public Licence Notice can be found as the
00013 // `COPYING' file in the root directory.
00014 //
00015 // The Vaucanson Group consists of people listed in the `AUTHORS' file.
00016 //
00017 #ifndef VCSN_MISC_UNIQUE_HXX
00018 # define VCSN_MISC_UNIQUE_HXX
00019 
00020 # include <vaucanson/misc/unique.hh>
00021 
00022 namespace vcsn {
00023   namespace misc {
00024 
00025     namespace unique {
00026 
00027       // This code solves a bug in GCC 4.0.0 for Apple Computer Inc.
00028 # if defined (__GNUC__)
00029 #  if defined (__GNUC_MINOR__) && defined (__GNUC_PATCHLEVEL__)
00030 #   if (__GNUC__ == 4) && (__GNUC_MINOR__ == 0) && (__GNUC_PATCHLEVEL__ == 0)
00031       template class UniqueMap<int>::TiSlot<int>;
00032 #   endif
00033 #  endif
00034 # endif
00035 
00036       template <>
00037       template <>
00038       inline
00039       unique_map::ti_slot::TiSlot (const std::type_info& _id) : id (_id)
00040       {
00041       }
00042 
00043       template <>
00044       template <>
00045       inline
00046       bool
00047       unique_map::ti_slot::
00048       operator== (const unique_map::ti_slot& other) const
00049       {
00050         return id == other.id;
00051       }
00052 
00053       template <>
00054       template <>
00055       inline
00056       bool unique_map::ti_slot::
00057       operator< (const unique_map::ti_slot& other) const
00058       {
00059         return id.before (other.id);
00060       }
00061 
00062       template <typename T>
00063       uniquelist<T>::~uniquelist ()
00064       {}
00065 
00066       inline
00067       unifiable::unifiable () : unique_ (false)
00068       {}
00069 
00070       inline
00071       unifiable::unifiable (const unifiable& ) : unique_ (false)
00072       {}
00073 
00074       template <typename T>
00075       const T& get (const T& v)
00076       {
00077         if (static_cast<const unifiable&> (v).unique_)
00078           return v;
00079 
00080         unique_map::map_t& m = unique_map::instance ();
00081 
00082         unique_map::map_t::iterator i = m.find (typeid (T));
00083         if (i == m.end ())
00084         {
00085           uniquelist<T> *l =
00086             static_cast<uniquelist<T>* > (m[typeid (T)] = new uniquelist<T>);
00087           l->push_front (v);
00088           static_cast<unifiable&> (l->front ()).unique_ = true;
00089           return l->front ();
00090         }
00091         uniquelist<T> *l =
00092           static_cast<uniquelist<T>*> (i->second);
00093         typename uniquelist<T>::const_iterator j;
00094         if ((j = std::find (l->begin (), l->end (), v)) == l->end ())
00095         {
00096           l->push_front (v);
00097           static_cast<unifiable&> (l->front ()).unique_ = true;
00098           return l->front ();
00099         }
00100         return *j;
00101       }
00102 
00103       template <typename T>
00104       const T* get (const T* v)
00105       {
00106         return & get (*v);
00107       }
00108 
00109       template <>
00110       inline
00111       uniquelist_base::~UniqueListBase () {}
00112 
00113       template <class T>
00114       typename UniqueMap<T>::map_t&
00115       UniqueMap<T>::instance ()
00116       {
00117         static unique_map instance_;
00118         return instance_.map_;
00119       }
00120 
00121       template <class T>
00122       UniqueMap<T>::UniqueMap ()
00123       {
00124       }
00125 
00126       template <class T>
00127       UniqueMap<T>::~UniqueMap ()
00128       {
00129         for (typename map_t::iterator i = map_.begin ();
00130              i != map_.end ();
00131              ++i)
00132           delete i->second;
00133       }
00134 
00135     } // unique
00136   } // misc
00137 } // vcsn
00138 
00139 #endif // ! VCSN_MISC_UNIQUE_HXX