00001 // [License] 00002 // The FreeBSD License 00003 // 00004 // Copyright (c) 2008-2009 Sebastian Mies <mies@edcft.de> 00005 // 00006 // Sebastian Mies 00007 // Gebhardstrasse 25 00008 // 76137 Karlsruhe 00009 // Germany 00010 // 00011 // Redistribution and use in source and binary forms, with or without 00012 // modification, are permitted provided that the following conditions are 00013 // met: 00014 // 00015 // 1. Redistributions of source code must retain the above copyright 00016 // notice, this list of conditions and the following disclaimer. 00017 // 2. Redistributions in binary form must reproduce the above copyright 00018 // notice, this list of conditions and the following disclaimer in the 00019 // documentation and/or other materials provided with the distribution. 00020 // 00021 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND 00022 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00023 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00024 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS 00025 // BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00026 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00027 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00028 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00029 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00030 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00031 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00032 // [License] 00033 00034 #ifndef VFACADE_HPP_ 00035 #define VFACADE_HPP_ 00036 00037 //--- USAGE INFORMATION -------------------------------------------------------- 00038 // 00039 // This header is used to easily implement a virtual facade design pattern. It 00040 // allows to specify a virtual wrapper interface to a non-virtual class. Look 00041 // at this example: 00042 // 00043 // <code> 00044 // // unspecified version 00045 // class to_string_definition : public vfacade_interface { 00046 // public: 00047 // virtual string to_string() const { 00048 // return "UNIMPLEMENTED: to_string()"; 00049 // }; 00050 // }; 00051 // 00052 // // delegation version 00053 // template<class T> 00054 // class vfacade_delegation<to_string_definition, T> : 00055 // public to_string_definition { 00056 // public: 00057 // virtual string to_string() const { 00058 // return get<T>().to_string(); 00059 // } 00060 // }; 00061 // 00062 // // final type 00063 // typedef vfacade<to_string_definition> vto_string; 00064 // </code> 00065 // 00066 // The to_string_definition specifies an unimplemented facade interface. Its 00067 // necessary for this class not to be pure-virtual. The vfacade_delegation 00068 // specialization implements a delegation any another non-virtual class T. 00069 // Finally the facade type is defined by using the vfacade template. Now, 00070 // we can use this facade, like in the following example: 00071 // 00072 // <code> 00073 // class A { 00074 // public: 00075 // string to_string() { 00076 // return "a hello from class A"; 00077 // } 00078 // }; 00079 // 00080 // void main() { 00081 // A something; 00082 // vto_string to_str = something; 00083 // cout << to_str->to_string() << endl; 00084 // } 00085 // </code> 00086 // 00087 // This example outputs "a hello from class A" by using the virtual facade. As 00088 // defined class A does not need to know about the facade -- it just implements 00089 // the needed methods. The to_string method is transparently bound to the 00090 // facade by the delegation implementation. 00091 // 00092 // The purpose of this virtual facade is simple: whenever you need a abstract 00093 // representation of non-virtual structures you can simply use a virtual facade. 00094 // It carries a vtable with the delegation to the non-virtual methods and a 00095 // pointer to the original object. Therefore it binds a vtable to a pointer 00096 // so vtable information is stored with the pointer and not with the object 00097 // itself. 00098 // 00099 //------------------------------------------------------------------------------ 00100 00101 // forward declaration 00102 template<class X, class Y> 00103 class vfacade_delegation; 00104 00111 template<class X> 00112 class vfacade { 00113 private: 00114 X value; 00115 00116 public: 00117 vfacade() { 00118 } 00119 00120 template<class Y> 00121 vfacade(const Y& _value) { 00122 vfacade_delegation<X, Y> v; 00123 v.set(_value); 00124 memcpy(&value, &v, sizeof(X)); 00125 } 00126 00127 template<class Y> 00128 vfacade<X>& operator=(const Y& _value) { 00129 vfacade_delegation<X, Y> v; 00130 v.set(_value); 00131 memcpy(&value, &v, sizeof(X)); 00132 return *this; 00133 } 00134 00135 vfacade(const vfacade<X>& v) { 00136 memcpy(&value, &v.value, sizeof(X)); 00137 } 00138 00139 vfacade<X>& operator=(const vfacade<X>& v ) { 00140 memcpy(&value, &v.value, sizeof(X)); 00141 return *this; 00142 } 00143 00144 X* operator->() { 00145 return &value; 00146 } 00147 00148 const X* operator->() const { 00149 return &value; 00150 } 00151 }; 00152 00158 class vfacade_interface { 00159 template<class X> friend class vfacade; 00160 00161 private: 00162 void* value; 00163 00164 protected: 00165 template<class X> X& get() const { 00166 return *((X*) value); 00167 } 00168 template<class X> void set(X& v) { 00169 value = (void*) &v; 00170 } 00171 00172 public: 00173 vfacade_interface() : 00174 value(NULL) { 00175 } 00176 00177 bool is_unspecified() const { 00178 return value == NULL; 00179 } 00180 00181 template<class Y> 00182 Y* ptr() { 00183 return (Y*)value; 00184 } 00185 00186 template<class Y> 00187 const Y* ptr() const { 00188 return (Y*)value; 00189 } 00190 00191 template<class Y> 00192 Y& cast_to() { 00193 return *ptr<Y>(); 00194 } 00195 00196 template<class Y> 00197 const Y& cast_to() const { 00198 return *ptr<Y>(); 00199 } 00200 }; 00201 00207 template<class T, class Y> 00208 class vfacade_delegation: public T { 00209 00210 }; 00211 00212 #endif