Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

more/gen/generic.h

Go to the documentation of this file.
00001 //  Copyright (C) 2001--2002  Petter Urkedal
00002 //
00003 //  This file is free software; you can redistribute it and/or modify
00004 //  it under the terms of the GNU General Public License as published by
00005 //  the Free Software Foundation; either version 2 of the License, or
00006 //  (at your option) any later version.
00007 //
00008 //  This file 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
00011 //  GNU General Public License for more details.
00012 //
00013 //  You should have received a copy of the GNU General Public License
00014 //  along with this program; if not, write to the Free Software
00015 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00016 //
00017 //  As a special exception, you may use this file as part of a free
00018 //  software library without restriction.  Specifically, if other files
00019 //  instantiate templates or use macros or inline functions from this
00020 //  file, or you compile this file and link it with other files to
00021 //  produce an executable, this file does not by itself cause the
00022 //  resulting executable to be covered by the GNU General Public
00023 //  License.  This exception does not however invalidate any other
00024 //  reasons why the executable file might be covered by the GNU General
00025 //  Public License.
00026 //
00027 //  $Id: generic.h,v 1.2 2002/08/24 13:57:38 petter_urkedal Exp $
00028 
00029 
00030 #ifndef MORE_GENERIC_H
00031 #define MORE_GENERIC_H
00032 
00033 #include <utility>
00034 #include <iterator>
00035 #include <new>
00036 #include <memory>
00037 
00038 namespace more {
00039 namespace gen {
00040 
00041   class generic;
00042 
00043   // These should be private types of generic, but we can't
00044   // specialize templates there.
00045   ///\if bits
00046   namespace bits_generic {
00047 
00048     struct vt_type
00049     {
00050         void (*construct_copy)(generic* dest, generic const& src);
00051         void (*destruct)(generic* dest);
00052     };
00053 
00054     template<typename T>
00055       struct scalar_vt
00056       {
00057           static void
00058           construct_copy(generic* obj, generic const& src)
00059           {
00060               if (sizeof(T) <= sizeof(void*))
00061                   new(&reinterpret_cast<T&>(obj->p))
00062                       T(reinterpret_cast<T const&>(src.p));
00063               else
00064                   obj->p = new T(*static_cast<T const*>(src.p));
00065           }
00066 
00067           static void
00068           destruct(generic* obj)
00069           {
00070               if (sizeof(T) <= sizeof(void*))
00071                   reinterpret_cast<T&>(obj->p).~T();
00072               else
00073                   delete static_cast<T*>(obj->p);
00074           }
00075 
00076           static vt_type et;
00077       };
00078 
00079     template<>
00080       struct scalar_vt<void>
00081       {
00082           static void construct_copy(generic* obj, generic const& src) {}
00083           static void destruct(generic* obj) {}
00084           static vt_type et;
00085       };
00086 
00087     template<typename T>
00088       struct vector_vt
00089       {
00090           struct layout {
00091               T* end;
00092               T x[1];
00093           };
00094           static T* begin(generic* x) {
00095               return static_cast<layout*>(x->p)->x;
00096           }
00097           static T* end(generic* x) {
00098               return static_cast<layout*>(x->p)->end;
00099           }
00100           static T const* begin(generic const* x) {
00101               return static_cast<layout const*>(x->p)->x;
00102           }
00103           static T const* end(generic const* x) {
00104               return static_cast<layout const*>(x->p)->end;
00105           }
00106           template<typename InputIterator>
00107             static void
00108             construct(generic* obj,
00109                       InputIterator first, InputIterator last) {
00110                 std::size_t n = std::distance(first, last);
00111                 layout* p = static_cast<layout*>
00112                     (::operator new(sizeof(layout) + sizeof(T)*(n-1)));
00113                 p->end = p->x + n;
00114                 obj->p = p;
00115                 std::uninitialized_copy(first, last, p->x);
00116             }
00117           static void
00118           construct_copy(generic* obj, generic const& src) {
00119               T const* first = begin(&src);
00120               T const* last = end(&src);
00121               std::size_t n = last - first;
00122               layout* p = static_cast<layout*>
00123                   (::operator new(sizeof(layout) + sizeof(T)*(n-1)));
00124               p->end = p->x + n;
00125               obj->p = p;
00126               std::uninitialized_copy(first, last, p->x);
00127           }
00128           static void
00129           destruct(generic* obj) {
00130               T* first = begin(obj);
00131               T* last = end(obj);
00132               while (first != last) {
00133                   first->~T();
00134                   ++first;
00135               }
00136               ::operator delete(obj->p);
00137           }
00138           static vt_type et;
00139       };
00140 
00141     template<typename T>
00142       vt_type scalar_vt<T>::et = { construct_copy, destruct };
00143     template<typename T>
00144       vt_type vector_vt<T>::et = { construct_copy, destruct };
00145 
00146   }
00147   ///\endif
00148 
00149   /** \class generic generic.h more/gen/generic.h
00150       A type which can hold an object or a range of any other copyable
00151       type.  The space overhead is one pointer for objects smaller or
00152       equal to sizeof(void*), and two pointers plus an allocation for
00153       bigger objects.  The time overhead, assuming optimalization,
00154       should be none for accessing small objects and a pointer
00155       dereference for accessing larger objects. Checking the object
00156       type is a pointer comparison.  */
00157   struct generic
00158   {
00159       generic()
00160           : m_vt(&bits_generic::scalar_vt<void>::et) {}
00161 
00162       generic(generic const& x)
00163           : m_vt(x.m_vt) { m_vt->construct_copy(this, x); }
00164 
00165       ~generic() { m_vt->destruct(this); }
00166 
00167       generic& operator=(generic const& rhs)
00168       {
00169           this->~generic();
00170           new(this) generic(rhs);
00171           return *this;
00172       }
00173 
00174       template<typename T>
00175         generic(T const& x)
00176         {
00177             m_vt = &bits_generic::scalar_vt<T>::et;
00178             if (sizeof(T) <= sizeof(void*))
00179                 new(&reinterpret_cast<T&>(p)) T(x);
00180             else
00181                 p = new T(x);
00182         }
00183 
00184       template<typename InputIterator>
00185         generic(InputIterator first, InputIterator last)
00186         {
00187             typedef typename std::iterator_traits<InputIterator>::value_type
00188                     value_type;
00189             m_vt = &bits_generic::vector_vt<value_type>::et;
00190             bits_generic::vector_vt<value_type>::construct(this, first, last);
00191         }
00192 
00193       template<typename T>
00194         bool is()
00195         {
00196             return m_vt == &bits_generic::scalar_vt<T>::et;
00197         }
00198 
00199       template<typename T>
00200         T&
00201         to()
00202         {
00203             if (sizeof(T) <= sizeof(void*))
00204                 return reinterpret_cast<T&>(p);
00205             else
00206                 return *static_cast<T*>(p);
00207         }
00208 
00209       template<typename T>
00210         T const&
00211         to() const
00212         {
00213             if (sizeof(T) <= sizeof(void*))
00214                 return reinterpret_cast<T const&>(p);
00215             else
00216                 return *static_cast<T const*>(p);
00217         }
00218 
00219       template<typename T>
00220         std::pair<T*, T*>
00221         to_range()
00222         {
00223             return std::pair<T*, T*>(bits_generic::vector_vt<T>::begin(this),
00224                                      bits_generic::vector_vt<T>::end(this));
00225         }
00226 
00227       template<typename T>
00228         std::pair<T const*, T const*>
00229         to_range() const
00230         {
00231             return std::pair<T const*, T const*>(
00232                 bits_generic::vector_vt<T>::begin(this),
00233                 bits_generic::vector_vt<T>::end(this));
00234         }
00235 
00236     private:
00237       bits_generic::vt_type* m_vt;
00238       void* p;
00239 
00240       template<typename T> friend class bits_generic::scalar_vt;
00241       template<typename T> friend class bits_generic::vector_vt;
00242   };
00243 
00244 }} // more::gen
00245 
00246 #endif

Generated on Sat Sep 7 19:11:12 2002 for more with Doxygen 1.2.13.1. Doxygen 1.2.13.1 is written and copyright 1997-2002 by Dimitri van Heesch.