00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef QGLIB_REFPOINTER_H
00020 #define QGLIB_REFPOINTER_H
00021
00022 #ifdef Q_MOC_RUN
00023 #define BOOST_TT_HAS_OPERATOR_HPP_INCLUDED
00024 #endif
00025
00026 #include "global.h"
00027 #include "type.h"
00028 #include "wrap.h"
00029 #include <cstddef>
00030 #include <boost/type_traits.hpp>
00031 #include <boost/utility/enable_if.hpp>
00032
00033 namespace QGlib {
00034
00035
00036 class Object;
00037 class Interface;
00038
00039
00040 namespace Private {
00041
00042 template <class T, class X>
00043 struct RefPointerEqualityCheck {};
00044
00045 template <class T, class X>
00046 struct RefPointerEqualityCheck<T, RefPointer<X> >
00047 {
00048 static inline bool check(const RefPointer<T> & self, const RefPointer<X> & other)
00049 {
00050 if (self.m_class && other.m_class) {
00051 return self.m_class->m_object == other.m_class->m_object;
00052 } else {
00053 return self.isNull() && other.isNull();
00054 }
00055 }
00056 };
00057
00058 template <class T, class X>
00059 struct RefPointerEqualityCheck<T, X*>
00060 {
00061 static inline bool check(const RefPointer<T> & self, X* const & other)
00062 {
00063 return self.m_class ? self.m_class->m_object == other : !other;
00064 }
00065 };
00066
00067 }
00068
00069
00090 template <class T>
00091 class RefPointer
00092 {
00093 public:
00094 inline RefPointer();
00095 inline ~RefPointer();
00096
00098 explicit inline RefPointer(T *cppClass);
00099
00100 template <class X>
00101 inline RefPointer(const RefPointer<X> & other);
00102 inline RefPointer(const RefPointer<T> & other);
00103
00104 template <class X>
00105 inline RefPointer<T> & operator=(const RefPointer<X> & other);
00106 inline RefPointer<T> & operator=(const RefPointer<T> & other);
00107
00121 template <class X>
00122 bool operator==(const X & other) const;
00123 template <class X>
00124 bool operator!=(const X & other) const;
00125
00128 void clear();
00129
00130 inline bool isNull() const;
00131 inline bool operator!() const;
00132 inline T *operator->() const;
00133
00140 inline operator typename T::CType*() const;
00141
00146 static RefPointer<T> wrap(typename T::CType *nativePtr, bool increaseRef = true);
00147
00149 template <class X>
00150 RefPointer<X> staticCast() const;
00151
00165 template <class X>
00166 RefPointer<X> dynamicCast() const;
00167
00168 private:
00169 template <class X> friend class RefPointer;
00170 template <class X, class Y> friend struct Private::RefPointerEqualityCheck;
00171
00172 template <class X>
00173 void assign(const RefPointer<X> & other);
00174
00175 T *m_class;
00176 };
00177
00182 class QTGLIB_EXPORT RefCountedObject
00183 {
00184 public:
00185 virtual ~RefCountedObject() {}
00186
00187 protected:
00188 template <class T> friend class RefPointer;
00189 template <class T, class X> friend struct Private::RefPointerEqualityCheck;
00190
00191 virtual void ref(bool increaseRef) = 0;
00192 virtual void unref() = 0;
00193
00194 template <class T>
00195 inline T* object() const;
00196
00197 void *m_object;
00198 };
00199
00200 template <class T>
00201 inline T* RefCountedObject::object() const
00202 {
00203 return static_cast<T* const>(m_object);
00204 }
00205
00206
00207 template <class T>
00208 inline RefPointer<T>::RefPointer()
00209 : m_class(NULL)
00210 {
00211 }
00212
00213 template <class T>
00214 inline RefPointer<T>::~RefPointer()
00215 {
00216 clear();
00217 }
00218
00219 template <class T>
00220 inline RefPointer<T>::RefPointer(T *cppClass)
00221 : m_class(cppClass)
00222 {
00223 static_cast<RefCountedObject*>(m_class)->ref(true);
00224 }
00225
00226 template <class T>
00227 template <class X>
00228 inline RefPointer<T>::RefPointer(const RefPointer<X> & other)
00229 : m_class(NULL)
00230 {
00231 assign(other);
00232 }
00233
00234 template <class T>
00235 inline RefPointer<T>::RefPointer(const RefPointer<T> & other)
00236 : m_class(NULL)
00237 {
00238 assign(other);
00239 }
00240
00241 template <class T>
00242 template <class X>
00243 inline RefPointer<T> & RefPointer<T>::operator=(const RefPointer<X> & other)
00244 {
00245 clear();
00246 assign(other);
00247 return *this;
00248 }
00249
00250 template <class T>
00251 inline RefPointer<T> & RefPointer<T>::operator=(const RefPointer<T> & other)
00252 {
00253 clear();
00254 assign(other);
00255 return *this;
00256 }
00257
00258 template <class T>
00259 template <class X>
00260 void RefPointer<T>::assign(const RefPointer<X> & other)
00261 {
00262
00263 QGLIB_STATIC_ASSERT((boost::is_base_of<T, X>::value),
00264 "Cannot implicitly cast a RefPointer down the hierarchy");
00265
00266 if (!other.isNull()) {
00267 m_class = static_cast<T*>(other.m_class);
00268 static_cast<RefCountedObject*>(m_class)->ref(true);
00269 }
00270 }
00271
00272 template <class T>
00273 template <class X>
00274 bool RefPointer<T>::operator==(const X & other) const
00275 {
00276 return Private::RefPointerEqualityCheck<T, X>::check(*this, other);
00277 }
00278
00279 template <class T>
00280 template <class X>
00281 bool RefPointer<T>::operator!=(const X & other) const
00282 {
00283 return !Private::RefPointerEqualityCheck<T, X>::check(*this, other);
00284 }
00285
00289 template <class T, class X>
00290
00291
00292 typename boost::enable_if_c<
00293 boost::is_pointer<X>::value &&
00294 !boost::is_same<X, typename boost::add_pointer<typename T::CType>::type>::value,
00295 bool
00296 >::type
00297 operator==(const X & other, const RefPointer<T> & self)
00298 {
00299 return Private::RefPointerEqualityCheck<T, X>::check(self, other);
00300 }
00301
00305 template <class T, class X>
00306
00307
00308 typename boost::enable_if_c<
00309 boost::is_pointer<X>::value &&
00310 !boost::is_same<X, typename boost::add_pointer<typename T::CType>::type>::value,
00311 bool
00312 >::type
00313 operator!=(const X & other, const RefPointer<T> & self)
00314 {
00315 return !Private::RefPointerEqualityCheck<T, X>::check(self, other);
00316 }
00317
00318 template <class T>
00319 void RefPointer<T>::clear()
00320 {
00321 if (!isNull()) {
00322 static_cast<RefCountedObject*>(m_class)->unref();
00323 m_class = NULL;
00324 }
00325 }
00326
00327
00328 template <class T>
00329 RefPointer<T> RefPointer<T>::wrap(typename T::CType *nativePtr, bool increaseRef)
00330 {
00331 RefPointer<T> ptr;
00332 if (nativePtr != NULL) {
00333 RefCountedObject *cppObj = WrapImpl<T>::wrap(nativePtr);
00334 cppObj->ref(increaseRef);
00335 ptr.m_class = dynamic_cast<T*>(cppObj);
00336 Q_ASSERT(ptr.m_class);
00337 }
00338 return ptr;
00339 }
00340
00341 template <class T>
00342 inline bool RefPointer<T>::isNull() const
00343 {
00344 return m_class == NULL;
00345 }
00346
00347 template <class T>
00348 inline bool RefPointer<T>::operator!() const
00349 {
00350 return m_class == NULL;
00351 }
00352
00353 template <class T>
00354 inline T *RefPointer<T>::operator->() const
00355 {
00356 Q_ASSERT_X(!isNull(), "RefPointer::operator->() const",
00357 "Attempted to dereference a null pointer");
00358 return m_class;
00359 }
00360
00361 template <class T>
00362 inline RefPointer<T>::operator typename T::CType*() const
00363 {
00364 return m_class ? static_cast<RefCountedObject*>(m_class)->object<typename T::CType>() : NULL;
00365 }
00366
00367 template <class T>
00368 template <class X>
00369 RefPointer<X> RefPointer<T>::staticCast() const
00370 {
00371 RefPointer<X> result;
00372 if (m_class) {
00373 static_cast<RefCountedObject*>(m_class)->ref(true);
00374 result.m_class = static_cast<X*>(m_class);
00375 }
00376 return result;
00377 }
00378
00379
00380 namespace Private {
00381
00382 template <typename T, typename X, typename Enable = void>
00383 struct IfaceDynamicCastImpl
00384 {
00385 static inline X *doCast(typename X::CType *obj)
00386 {
00387 Q_UNUSED(obj);
00388 return NULL;
00389 }
00390 };
00391
00392
00393
00394 template <typename T, typename X>
00395 struct IfaceDynamicCastImpl<T, X,
00396 typename boost::enable_if_c<
00397
00398
00399 (boost::is_base_of<Interface, X>::value &&
00400 !boost::is_base_of<Object, X>::value &&
00401 boost::is_base_of<Object, T>::value)
00402 >::type
00403 >
00404 {
00405 static inline X *doCast(typename X::CType *obj)
00406 {
00407 X *targetClass = NULL;
00408
00409
00410
00411 if (Type::fromInstance(obj).isA(GetType<X>()))
00412 {
00413 targetClass = dynamic_cast<X*>(Private::wrapInterface(GetType<X>(), obj));
00414 Q_ASSERT(targetClass);
00415 }
00416
00417 return targetClass;
00418 }
00419 };
00420
00421
00422
00423 template <typename T, typename X>
00424 struct IfaceDynamicCastImpl<T, X,
00425 typename boost::enable_if_c<
00426
00427
00428 (boost::is_base_of<Interface, T>::value &&
00429 !boost::is_base_of<Object, T>::value)
00430 >::type
00431 >
00432 {
00433 static inline X *doCast(typename X::CType *obj)
00434 {
00435
00436
00437 RefCountedObject *cppClass = Private::wrapObject(obj);
00438
00439
00440 X *targetClass = dynamic_cast<X*>(cppClass);
00441
00442 if (!targetClass) {
00443
00444
00445
00446
00447 if (boost::is_base_of<Interface, X>::value &&
00448 !boost::is_base_of<Object, X>::value &&
00449 Type::fromInstance(obj).isA(GetType<X>()))
00450 {
00451 targetClass = dynamic_cast<X*>(Private::wrapInterface(GetType<X>(), obj));
00452 Q_ASSERT(targetClass);
00453 }
00454 }
00455
00456 return targetClass;
00457 }
00458 };
00459
00460 }
00461
00462
00463 template <class T>
00464 template <class X>
00465 RefPointer<X> RefPointer<T>::dynamicCast() const
00466 {
00467 RefPointer<X> result;
00468 if (m_class) {
00469 X *targetClass = dynamic_cast<X*>(m_class);
00470 if (!targetClass) {
00471
00472
00473 typename X::CType *obj = static_cast<RefCountedObject*>(m_class)->object<typename X::CType>();
00474 targetClass = Private::IfaceDynamicCastImpl<T, X>::doCast(obj);
00475 }
00476
00477 if (targetClass) {
00478 static_cast<RefCountedObject*>(targetClass)->ref(true);
00479 result.m_class = targetClass;
00480 }
00481 }
00482
00483 return result;
00484 }
00485
00486
00487 template <class T>
00488 struct GetTypeImpl< RefPointer<T> >
00489 {
00490 inline operator Type() { return GetType<T>(); }
00491 };
00492
00493 }
00494
00495 #endif