type.hh

00001 // Copyright (C) 2001, 2002, 2003, 2004  EPITA Research and Development Laboratory
00002 //
00003 // This file is part of the Olena Library.  This library is free
00004 // software; you can redistribute it and/or modify it under the terms
00005 // of the GNU General Public License version 2 as published by the
00006 // Free Software Foundation.
00007 //
00008 // This library is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011 // General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU General Public License
00014 // along with this library; see the file COPYING.  If not, write to
00015 // the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
00016 // MA 02111-1307, USA.
00017 //
00018 // As a special exception, you may use this file as part of a free
00019 // software library without restriction.  Specifically, if other files
00020 // instantiate templates or use macros or inline functions from this
00021 // file, or you compile this file and link it with other files to
00022 // produce an executable, this file does not by itself cause the
00023 // resulting executable to be covered by the GNU General Public
00024 // License.  This exception does not however invalidate any other
00025 // reasons why the executable file might be covered by the GNU General
00026 // Public License.
00027 
00028 #ifndef METALIC_TYPE_HH
00029 # define METALIC_TYPE_HH
00030 
00031 # include <mlc/config/system.hh>
00032 # include <mlc/bool.hh>
00033 
00034 # include <string>
00035 # include <cassert>
00036 
00037 // FIXME: make a hierarchy of any with the different implementations
00038 
00039 // any and any_with_diamond types are not defined in namespace mlc to
00040 // avoid namespace clashes. Indeed, a type inheriting from another in
00041 // a namespace foo will have implicit access to the foo namespace.
00042 
00043 namespace mlc_hierarchy
00044 {
00045 
00046   /*-----------------.
00047   | any_with_diamond |
00048   `-----------------*/
00049 
00050   template<class E>
00051   class any_with_diamond
00052   {
00053   public:
00054     typedef E exact_type;
00055 
00056     E& exact()
00057     {
00058       return *(E*)((char*)this - exact_offset);
00059     }
00060     const E& exact() const
00061     {
00062       return *(const E*)((const char*)this - exact_offset);
00063     }
00064 
00065     static std::string name()
00066     {
00067       return std::string("any_with_diamond<") + E::name() + ">";
00068     }
00069 
00070   private:
00071     // This stores the actual value of the offset between the this
00072     // pointer and the address of the exact type. This enables diamond
00073     // shaped hierarchies (static_cast can't and reinterpret_cast or
00074     // (Exact*)(void*) cast are unsafe and compiler dependent).
00075     static const int exact_offset;
00076 
00077     // Utility members used to determine the exact_offset
00078     static const E exact_obj;
00079     static const any_with_diamond<E>& ref_exact_obj;
00080   };
00081 
00082   template <class E>
00083   const E any_with_diamond<E>::exact_obj = E();
00084 
00085   template <class E>
00086   const any_with_diamond<E>&
00087   any_with_diamond<E>::ref_exact_obj = any_with_diamond<E>::exact_obj;
00088 
00089   template <class E>
00090   const int any_with_diamond<E>::exact_offset =
00091   (const char*)(void*)(&any_with_diamond<E>::ref_exact_obj)
00092     - (const char*)(void*)(&any_with_diamond<E>::exact_obj);
00093 
00094 
00095   // Warning, this class does not allow diamond hierarchies, consider
00096   // any_with_diamond if you really need it.
00097 
00098   /*----.
00099   | any |
00100   `----*/
00101 
00102   template<class E>
00103   class any
00104   {
00105   public:
00106     typedef E exact_type;
00107 
00108     E& exact()             { return static_cast<E&>(*this); }
00109     const E& exact() const { return static_cast<const E&>(*this); }
00110 
00111     static std::string name()
00112     {
00113       return std::string("any<") + E::name() + ">";
00114     }
00115 
00116   protected:
00117     any() {}
00118   };
00119 
00120 } // end of namespace mlc_hierarchy
00121 
00122 namespace mlc
00123 {
00124 
00125   /*-------------.
00126   | Useful types |
00127   `-------------*/
00128 
00129   struct undefined {};
00130 
00131   class final
00132   {
00133   public:
00134     static std::string name() { return "final"; }
00135   protected:
00136     final() {}
00137   };
00138 
00139   class top
00140   {
00141   public:
00142     static std::string name() { return ""; }
00143   protected:
00144     top() {}
00145   };
00146 
00147   /*------------------.
00148   | assign_exact_this |
00149   `------------------*/
00150 
00151   // Helper struct for any_with_diamond hierarchies. See
00152   // mlc_init_static_hierarchy.
00153 
00154   template <class Exact, class Final>
00155   struct assign_exact_offset
00156   {
00157     template <class E>
00158     static void doit(const E&)
00159     {}
00160   };
00161 
00162   template <>
00163   struct assign_exact_offset<mlc::final, mlc::final>
00164   {
00165     template <class E>
00166     static void doit(const E* t)
00167     {
00168       if (!mlc_hierarchy::any_with_diamond<E>::offset_assigned)
00169         {
00170           mlc_hierarchy::any_with_diamond<E>::exact_offset =
00171             (const char*)
00172             static_cast<const mlc_hierarchy::any_with_diamond<E>*>(t)
00173             - (const char*) t;
00174           mlc_hierarchy::any_with_diamond<E>::offset_assigned = true;
00175         }
00176     }
00177   };
00178 
00179   /*-------------.
00180   | exact traits |
00181   `-------------*/
00182 
00183   template<class T>
00184   struct exact
00185   {
00186     typedef typename T::exact_type ret;
00187   };
00188 
00189   template<class T>
00190   struct exact<const T>
00191   {
00192     typedef const typename exact<T>::ret ret;
00193   };
00194 
00195   template<class T>
00196   struct exact<T*>
00197   {
00198     typedef typename exact<T>::ret* ret;
00199   };
00200 
00201   template<class T>
00202   struct exact<T&>
00203   {
00204     typedef typename exact<T>::ret& ret;
00205   };
00206 
00207   /*---------.
00208   | exact_vt |
00209   `---------*/
00210 
00211   //
00212   //  exact virtual type traits
00213   //  (inheritance determination)
00214   //
00215   //  If Exact is mlc::final return T else return Exact
00216 
00217   template<class T, class Exact>
00218   struct exact_vt
00219   {
00220     typedef Exact ret;
00221   };
00222 
00223   template<class Exact>
00224   struct exact_vt<Exact,final>
00225   {
00226     typedef Exact ret;
00227   };
00228 
00229 } // end of namespace mlc
00230 
00231 /*-------------.
00232 | exact macros |
00233 `-------------*/
00234 
00235 // Return the exact type of a given type.
00236 
00237 # define mlc_exact_type(T) typename mlc::exact< T >::ret
00238 # define mlc_exact_type_(T) mlc::exact< T >::ret
00239 
00240 // Return the exact virtual type of two given types (inheritance determination).
00241 
00242 # define mlc_exact_vt_type(T, Exact)            typename mlc::exact_vt<T, Exact >::ret
00243 # define mlc_2_exact_vt_type(self, T, Exact)    typename mlc::exact_vt<self<T, Exact >, Exact >::ret
00244 # define mlc_exact_vt_type_(T, Exact)           mlc::exact_vt<T, Exact >::ret
00245 # define mlc_2_exact_vt_type_(self, T, Exact)   mlc::exact_vt<self<T, Exact >, Exact >::ret
00246 
00247 namespace mlc
00248 {
00249 
00250   /*-------------------.
00251   | to_exact functions |
00252   `-------------------*/
00253 
00254   template<class T> inline
00255   mlc_exact_type(T)&
00256   to_exact(T& ref)
00257   {
00258     return ref.exact();
00259   }
00260 
00261   template<class T> inline
00262   const mlc_exact_type(T)&
00263   to_exact(const T& ref)
00264   {
00265     return ref.exact();
00266   }
00267 
00268   template<class T> inline
00269   mlc_exact_type(T)*
00270   to_exact(T* ptr)
00271   {
00272     return &ptr->exact();
00273   }
00274 
00275   template<class T> inline
00276   const mlc_exact_type(T)*
00277   to_exact(const T* ptr)
00278   {
00279     return &ptr->exact();
00280   }
00281 
00282 } // end of namespace mlc
00283 
00284 /*---------------.
00285 | mlc_find_exact |
00286 `---------------*/
00287 
00288 // FIXME: uncomment when variadic macros become standardized
00289 
00290 // #define mlc_find_exact(...)
00291 // typename mlc::exact_vt<__VA_ARGS__>::ret
00292 // #define mlc_find_exact_(...)
00293 // mlc::exact_vt<__VA_ARGS__>::ret
00294 
00295 /*--------------------------.
00296 | mlc_init_static_hierarchy |
00297 `--------------------------*/
00298 
00299 // # define mlc_init_static_hierarchy(Exact)
00300 // mlc::assign_exact_offset<Exact, mlc::final>::doit(this)
00301 
00302 // FIXME: this is for backward compatibility purposes only.  This
00303 // macro is called in every constructor of the classes, so we let them
00304 // in place for the moment until we are sure that the static offset
00305 // method works fine.
00306 
00307 # define mlc_init_static_hierarchy(Exact)
00308 
00309 /*---------.
00310 | dispatch |
00311 `---------*/
00312 
00313 # define mlc_dispatch(Fun)                      return exact().Fun##_impl
00314 
00315 #endif // ! METALIC_TYPE_HH

Generated on Thu Apr 15 20:13:15 2004 for Olena by doxygen 1.3.6-20040222