akonadi
itempayloadinternals_p.h
00001 /* 00002 Copyright (c) 2007 Till Adam <adam@kde.org> 00003 00004 This library is free software; you can redistribute it and/or modify it 00005 under the terms of the GNU Library General Public License as published by 00006 the Free Software Foundation; either version 2 of the License, or (at your 00007 option) any later version. 00008 00009 This library is distributed in the hope that it will be useful, but WITHOUT 00010 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00011 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public 00012 License for more details. 00013 00014 You should have received a copy of the GNU Library General Public License 00015 along with this library; see the file COPYING.LIB. If not, write to the 00016 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 00017 02110-1301, USA. 00018 */ 00019 00020 #ifndef ITEMPAYLOADINTERNALS_P_H 00021 #define ITEMPAYLOADINTERNALS_P_H 00022 00023 #include <kpimutils/supertrait.h> 00024 00025 #include <QtCore/QtGlobal> 00026 #include <QtCore/QSharedPointer> 00027 #include <QtCore/QMetaType> 00028 00029 #include <boost/shared_ptr.hpp> 00030 #include <boost/type_traits/is_same.hpp> 00031 #include <boost/mpl/eval_if.hpp> 00032 #include <boost/mpl/identity.hpp> 00033 #include <boost/utility/enable_if.hpp> 00034 00035 #include <typeinfo> 00036 00037 #include "exception.h" 00038 00039 //@cond PRIVATE Doxygen 1.7.1 hangs processing this file. so skip it. 00040 //for more info, see https://bugzilla.gnome.org/show_bug.cgi?id=531637 00041 00042 /* WARNING 00043 * The below is an implementation detail of the Item class. It is not to be 00044 * considered public API, and subject to change without notice 00045 */ 00046 00047 namespace Akonadi { 00048 namespace Internal { 00049 00050 template <typename T> 00051 struct has_clone_method { 00052 private: 00053 template <typename S, S * (S::*)() const> struct sfinae {}; 00054 struct No {}; 00055 struct Yes { No no[2]; }; 00056 template <typename S> static No test( ... ); 00057 template <typename S> static Yes test( sfinae<S,&S::clone> * ); 00058 public: 00059 static const bool value = sizeof( test<T>(0) ) == sizeof( Yes ) ; 00060 }; 00061 00062 template <typename T, bool b> 00063 struct clone_traits_helper { 00064 // runtime error (commented in) or compiletime error (commented out)? 00065 // ### runtime error, until we check has_clone_method in the 00066 // ### Item::payload<T> impl directly... 00067 template <typename U> 00068 static T * clone( U ) { return 0; } 00069 }; 00070 00071 template <typename T> 00072 struct clone_traits_helper<T,true> { 00073 static T * clone( T * t ) { return t ? t->clone() : 0 ; } 00074 }; 00075 00076 template <typename T> 00077 struct clone_traits : clone_traits_helper<T, has_clone_method<T>::value> {}; 00078 00079 template <typename T> 00080 struct shared_pointer_traits { 00081 static const bool defined = false; 00082 }; 00083 00084 template <typename T> 00085 struct shared_pointer_traits< boost::shared_ptr<T> > { 00086 static const bool defined = true; 00087 typedef T element_type; 00088 template <typename S> 00089 struct make { typedef boost::shared_ptr<S> type; }; 00090 typedef QSharedPointer<T> next_shared_ptr; 00091 }; 00092 00093 template <typename T> 00094 struct shared_pointer_traits< QSharedPointer<T> > { 00095 static const bool defined = true; 00096 typedef T element_type; 00097 template <typename S> 00098 struct make { typedef QSharedPointer<S> type; }; 00099 typedef boost::shared_ptr<T> next_shared_ptr; 00100 }; 00101 00102 template <typename T> 00103 struct is_shared_pointer { 00104 static const bool value = shared_pointer_traits<T>::defined; 00105 }; 00106 00107 template <typename T> 00108 struct get_hierarchy_root; 00109 00110 template <typename T, typename S> 00111 struct get_hierarchy_root_recurse 00112 : get_hierarchy_root<S> {}; 00113 00114 template <typename T> 00115 struct get_hierarchy_root_recurse<T,T> 00116 : boost::mpl::identity<T> {}; 00117 00118 template <typename T> 00119 struct get_hierarchy_root 00120 : get_hierarchy_root_recurse< T, typename ::KPIMUtils::SuperClass<T>::Type > {}; 00121 00122 template <typename T> 00123 struct get_hierarchy_root< boost::shared_ptr<T> > { 00124 typedef boost::shared_ptr< typename get_hierarchy_root<T>::type > type; 00125 }; 00126 00127 template <typename T> 00128 struct get_hierarchy_root< QSharedPointer<T> > { 00129 typedef QSharedPointer< typename get_hierarchy_root<T>::type > type; 00130 }; 00131 00132 00139 template <typename T> struct PayloadTrait 00140 { 00142 typedef T ElementType; 00143 // the metatype id for the element type, or for pointer-to-element 00144 // type, if in a shared pointer 00145 static int elementMetaTypeId() { return qMetaTypeId<T>(); } 00148 typedef typename KPIMUtils::SuperClass<T>::Type SuperElementType; 00150 typedef T Type; 00154 typedef typename KPIMUtils::SuperClass<T>::Type SuperType; 00157 static const bool isPolymorphic = false; 00159 static inline bool isNull( const Type & ) { return true; } 00162 template <typename U> static inline Type castFrom( const U& ) 00163 { 00164 throw PayloadException( "you should never get here" ); 00165 } 00167 template <typename U> static inline bool canCastFrom( const U& ) 00168 { 00169 return false; 00170 } 00172 template <typename U> static inline U castTo( const Type& ) 00173 { 00174 throw PayloadException( "you should never get here" ); 00175 } 00176 template <typename U> static T clone( const U & ) 00177 { 00178 throw PayloadException( "clone: you should never get here" ); 00179 } 00181 static const unsigned int sharedPointerId = 0; 00182 }; 00183 00189 template <typename T> struct PayloadTrait<boost::shared_ptr<T> > 00190 { 00191 typedef T ElementType; 00192 static int elementMetaTypeId() { return qMetaTypeId<T*>(); } 00193 typedef typename KPIMUtils::SuperClass<T>::Type SuperElementType; 00194 typedef boost::shared_ptr<ElementType> Type; 00195 typedef boost::shared_ptr<SuperElementType> SuperType; 00196 static const bool isPolymorphic = !boost::is_same<ElementType, SuperElementType>::value; 00197 static inline bool isNull( const Type &p ) { return p.get() == 0; } 00198 template <typename U> static inline Type castFrom( const boost::shared_ptr<U> &p ) 00199 { 00200 const Type sp = boost::dynamic_pointer_cast<T,U>( p ); 00201 if ( sp.get() != 0 || p.get() == 0 ) 00202 return sp; 00203 throw PayloadException( "boost::dynamic_pointer_cast failed" ); 00204 } 00205 template <typename U> static inline bool canCastFrom( const boost::shared_ptr<U> &p ) 00206 { 00207 const Type sp = boost::dynamic_pointer_cast<T,U>( p ); 00208 return sp.get() != 0 || p.get() == 0; 00209 } 00210 template <typename U> static inline boost::shared_ptr<U> castTo( const Type &p ) 00211 { 00212 const boost::shared_ptr<U> sp = boost::dynamic_pointer_cast<U>( p ); 00213 return sp; 00214 } 00215 static boost::shared_ptr<T> clone( const QSharedPointer<T> & t ) { 00216 if ( T * nt = clone_traits<T>::clone( t.data() ) ) 00217 return boost::shared_ptr<T>( nt ); 00218 else 00219 return boost::shared_ptr<T>(); 00220 } 00221 static const unsigned int sharedPointerId = 1; 00222 }; 00223 00229 template <typename T> struct PayloadTrait<QSharedPointer<T> > 00230 { 00231 typedef T ElementType; 00232 static int elementMetaTypeId() { return qMetaTypeId<T*>(); } 00233 typedef typename KPIMUtils::SuperClass<T>::Type SuperElementType; 00234 typedef QSharedPointer<T> Type; 00235 typedef QSharedPointer<SuperElementType> SuperType; 00236 static const bool isPolymorphic = !boost::is_same<ElementType, SuperElementType>::value; 00237 static inline bool isNull( const Type &p ) { return p.isNull(); } 00238 template <typename U> static inline Type castFrom( const QSharedPointer<U> &p ) 00239 { 00240 const Type sp = qSharedPointerDynamicCast<T,U>( p ); 00241 if ( !sp.isNull() || p.isNull() ) 00242 return sp; 00243 throw PayloadException( "qSharedPointerDynamicCast failed" ); 00244 } 00245 template <typename U> static inline bool canCastFrom( const QSharedPointer<U> &p ) 00246 { 00247 const Type sp = qSharedPointerDynamicCast<T,U>( p ); 00248 return !sp.isNull() || p.isNull(); 00249 } 00250 template <typename U> static inline QSharedPointer<U> castTo( const Type &p ) 00251 { 00252 const QSharedPointer<U> sp = qSharedPointerDynamicCast<U,T>( p ); 00253 return sp; 00254 } 00255 static QSharedPointer<T> clone( const boost::shared_ptr<T> & t ) { 00256 if ( T * nt = clone_traits<T>::clone( t.get() ) ) 00257 return QSharedPointer<T>( nt ); 00258 else 00259 return QSharedPointer<T>(); 00260 } 00261 static const unsigned int sharedPointerId = 2; 00262 }; 00263 00264 00265 } 00266 00272 struct PayloadBase 00273 { 00274 virtual ~PayloadBase() { } 00275 virtual PayloadBase * clone() const = 0; 00276 virtual const char* typeName() const = 0; 00277 }; 00278 00284 template <typename T> 00285 struct Payload : public PayloadBase 00286 { 00287 Payload() {}; 00288 Payload( const T& p ) : payload( p ) {} 00289 00290 PayloadBase * clone() const 00291 { 00292 return new Payload<T>( const_cast<Payload<T>* >(this)->payload); 00293 } 00294 00295 const char* typeName() const 00296 { 00297 return typeid(const_cast<Payload<T>*> (this)).name(); 00298 } 00299 00300 T payload; 00301 }; 00302 00307 template <typename T> 00308 struct Payload<T*> : public PayloadBase 00309 { 00310 }; 00311 00312 namespace Internal { 00313 00318 template <typename T> inline Payload<T>* payload_cast( PayloadBase* payloadBase ) 00319 { 00320 Payload<T> *p = dynamic_cast<Payload<T>*>( payloadBase ); 00321 // try harder to cast, workaround for some gcc issue with template instances in multiple DSO's 00322 if ( !p && payloadBase && strcmp( payloadBase->typeName(), typeid(p).name() ) == 0 ) { 00323 p = static_cast<Payload<T>*>( payloadBase ); 00324 } 00325 return p; 00326 } 00327 00328 } 00329 00330 } 00331 //@endcond 00332 00333 #endif 00334
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Thu May 10 2012 22:18:33 by doxygen 1.8.0 written by Dimitri van Heesch, © 1997-2006
Documentation copyright © 1996-2012 The KDE developers.
Generated on Thu May 10 2012 22:18:33 by doxygen 1.8.0 written by Dimitri van Heesch, © 1997-2006
KDE's Doxygen guidelines are available online.