Mirror reflection library 0.5.13
|
00001 00009 #ifndef MIRROR_RAW_PTR_RAW_PTR_1011291729_HPP 00010 #define MIRROR_RAW_PTR_RAW_PTR_1011291729_HPP 00011 00012 #include <cstdlib> 00013 #include <memory> 00014 #include <mirror/config.hpp> 00015 #include <mirror/meta_prog/identity.hpp> 00016 #include <mirror/raw_ptr/auditor.hpp> 00017 00018 #if MIRROR_NO_RTTI 00019 #include <mirror/raw_ptr/int_seq_cmp.hpp> 00020 #else 00021 #include <mirror/raw_ptr/type_info_cmp.hpp> 00022 #endif 00023 00024 #include <exception> 00025 00026 MIRROR_NAMESPACE_BEGIN 00027 00056 namespace aux { 00057 00058 // Forward declaration of raw pointer base class 00059 template <typename BasePtrType> 00060 class raw_ptr_base; 00061 00062 // Specialization for void* 00063 template <> 00064 class raw_ptr_base<void*> 00065 { 00066 protected: 00067 void* ptr; 00068 public: 00069 typedef void* pointer_type; 00070 00071 inline raw_ptr_base(void) 00072 : ptr(nullptr) 00073 { } 00074 00075 template <typename T> 00076 inline raw_ptr_base(T* p) 00077 : ptr((void*)p) 00078 { } 00079 00080 template <typename T> 00081 inline raw_ptr_base(const std::shared_ptr<T>& sp) 00082 : ptr((void*)sp.get()) 00083 { } 00084 00085 template <typename T> 00086 inline raw_ptr_base(std::unique_ptr<T>&& sp) 00087 : ptr((void*)sp.release()) 00088 { } 00089 00090 template <typename T> 00091 friend inline T* do_raw_cast( 00092 mp::identity<T*>, 00093 const raw_ptr_base& rp 00094 ) 00095 { 00096 return (T*)rp.ptr; 00097 } 00098 00099 template <typename T> 00100 friend inline const T* do_raw_cast( 00101 mp::identity<const T*>, 00102 const raw_ptr_base& rp 00103 ) 00104 { 00105 return (const T*)rp.ptr; 00106 } 00107 }; 00108 00109 // Specialization for shared_ptr 00110 template <> 00111 class raw_ptr_base<std::shared_ptr<void> > 00112 { 00113 protected: 00114 typedef std::shared_ptr<void> pointer_type; 00115 00116 std::shared_ptr<void> ptr; 00117 00118 inline raw_ptr_base(void){ } 00119 00120 template <typename T> 00121 inline raw_ptr_base(const std::shared_ptr<T>& p) 00122 : ptr(p, (void*)p.get()) 00123 { } 00124 00125 template <typename T> 00126 inline raw_ptr_base(std::unique_ptr<T>&& p) 00127 : ptr(std::move(p)) 00128 { } 00129 00130 template <typename T> 00131 friend inline std::shared_ptr<T> do_raw_cast( 00132 mp::identity<std::shared_ptr<T> >, 00133 const raw_ptr_base& rp 00134 ) 00135 { 00136 return std::shared_ptr<T>( 00137 rp.ptr, 00138 (T*)rp.ptr.get() 00139 ); 00140 } 00141 public: 00142 }; 00143 00144 // Specialization for unique_ptr 00145 template <> 00146 class raw_ptr_base<std::unique_ptr<void> > 00147 { 00148 protected: 00149 typedef std::unique_ptr<void> pointer_type; 00150 00151 std::unique_ptr<void> ptr; 00152 00153 inline raw_ptr_base(void){ } 00154 00155 template <typename T> 00156 inline raw_ptr_base(std::unique_ptr<T>&& p) 00157 : ptr((void*)p.release(), p.get_deleter()) 00158 { } 00159 00160 // no copying 00161 raw_ptr_base(const raw_ptr_base& other) = delete; 00162 00163 inline raw_ptr_base(raw_ptr_base&& other) 00164 : ptr(std::move(other.ptr)) 00165 { } 00166 00167 template <typename T, typename D> 00168 friend inline std::unique_ptr<T, D> do_raw_cast( 00169 mp::identity<std::unique_ptr<T, D> >, 00170 raw_ptr_base&& rp 00171 ) 00172 { 00173 return std::move(std::unique_ptr<T, D>( 00174 (T*)rp.ptr.release(), 00175 D() 00176 //TODO: D(rp.ptr.get_deleter()) 00177 )); 00178 } 00179 public: 00180 }; 00181 00182 // Policy doing nothing at a bad cast 00183 struct do_nothing_at_bad_cast_policy 00184 { 00185 static inline bool bad_cast_handler(void) 00186 { 00187 return false; 00188 } 00189 }; 00190 00191 // Policy throwing std::bad_cast when a bad cast happens 00192 struct throw_at_bad_cast_policy 00193 { 00194 static bool bad_cast_handler(void) 00195 { 00196 throw std::bad_cast(); 00197 } 00198 }; 00199 00200 // Policy aborting the process when a bad cast happens 00201 struct abort_at_bad_cast_policy 00202 { 00203 static bool bad_cast_handler(void) 00204 { 00205 std::abort(); 00206 return false; 00207 } 00208 }; 00209 00210 } // namespace aux 00211 00213 00216 template < 00217 class Auditor, 00218 class BadCastPolicy, 00219 typename BasePtrType 00220 > 00221 class raw_ptr_templ : public aux::raw_ptr_base<BasePtrType> 00222 { 00223 private: 00224 // helper typedef of the base implementation 00225 typedef aux::raw_ptr_base<BasePtrType> base_class; 00226 00227 // The bad cast policy 00228 BadCastPolicy bad_cast_policy; 00229 00230 // The pointer cast auditor instance 00231 Auditor auditor; 00232 00233 // does checks before the cast and performs some actions if necessary 00234 template <typename T> 00235 bool audit_cast(mp::identity<T*>) const 00236 { 00237 // if the cast is allowed 00238 if(auditor.convertible_to(Auditor((T*)nullptr))) 00239 return true; 00240 // use the policy's handler function 00241 return bad_cast_policy.bad_cast_handler(); 00242 } 00243 00244 template < 00245 template <typename, typename ... > class SmartPtr, 00246 typename T, 00247 typename ... P 00248 > 00249 inline bool audit_cast(mp::identity<SmartPtr<T, P...> >) const 00250 { 00251 return audit_cast(mp::identity<T*>()); 00252 } 00253 public: 00254 typedef BasePtrType base_ptr_type; 00255 00256 inline const Auditor& get_auditor(void) const 00257 { 00258 return auditor; 00259 } 00260 00261 raw_ptr_templ(void) = default; 00262 00263 template <typename T> 00264 explicit raw_ptr_templ(T* ptr) 00265 : base_class(ptr) 00266 , auditor(ptr) 00267 { } 00268 00269 raw_ptr_templ(const raw_ptr_templ& other) 00270 : base_class(other) 00271 , auditor(other.auditor) 00272 { } 00273 00274 raw_ptr_templ(raw_ptr_templ&& other) 00275 : base_class(std::move(other)) 00276 , auditor(std::move(other.auditor)) 00277 { } 00278 00279 template < 00280 template <typename, typename ...> class SmartPtr, 00281 typename T, 00282 typename ... P 00283 > 00284 explicit raw_ptr_templ(const SmartPtr<T, P...>& ptr) 00285 : base_class(ptr) 00286 , auditor((T*)nullptr) 00287 { } 00288 00289 template < 00290 template <typename, typename ...> class SmartPtr, 00291 typename T, 00292 typename ... P 00293 > 00294 explicit raw_ptr_templ(SmartPtr<T, P...>&& ptr) 00295 : base_class(std::move(ptr)) 00296 , auditor((T*)nullptr) 00297 { } 00298 00299 template <class OtherBadCastPolicy, typename OtherBasePtrType> 00300 explicit raw_ptr_templ( 00301 const raw_ptr_templ< 00302 Auditor, 00303 OtherBadCastPolicy, 00304 OtherBasePtrType 00305 >& other 00306 ): base_class(other.get()) 00307 , auditor(other.get_auditor()) 00308 { } 00309 00310 template <typename T> 00311 raw_ptr_templ& operator = (T* a_ptr) 00312 { 00313 *this = base_class(a_ptr); 00314 auditor = Auditor(a_ptr); 00315 return *this; 00316 } 00317 00318 raw_ptr_templ& operator = (raw_ptr_templ&& other) 00319 { 00320 this->ptr = std::move(other.ptr); 00321 auditor = std::move(other.auditor); 00322 return *this; 00323 } 00324 00325 template < 00326 template <typename, typename ...> class SmartPtr, 00327 typename T, 00328 typename ... P 00329 > 00330 raw_ptr_templ& operator = (const SmartPtr<T, P ...>& a_ptr) 00331 { 00332 *this = base_class(a_ptr); 00333 auditor = Auditor((T*)nullptr); 00334 return *this; 00335 } 00336 00337 template <class OtherBadCastPolicy, typename OtherBasePtrType> 00338 raw_ptr_templ& operator = ( 00339 const raw_ptr_templ< 00340 Auditor, 00341 OtherBadCastPolicy, 00342 OtherBasePtrType 00343 >& other 00344 ) 00345 { 00346 *this = base_class(other.get()); 00347 auditor = other.get_auditor(); 00348 return *this; 00349 } 00350 00351 // Conversion to bool 00352 inline operator bool (void) const 00353 { 00354 return bool(this->ptr); 00355 } 00356 00357 // Logical negation 00358 inline bool operator !(void) const 00359 { 00360 return bool(!this->ptr); 00361 } 00362 00363 inline const BasePtrType& get(void) const 00364 { 00365 return this->ptr; 00366 } 00367 00368 template <typename T> 00369 friend T audited_raw_cast( 00370 mp::identity<T> tid, 00371 const raw_ptr_templ& rp 00372 ) 00373 { 00374 if(rp.audit_cast(tid)) 00375 return do_raw_cast(tid, rp); 00376 else return T(); 00377 } 00378 00379 template <typename T> 00380 friend T audited_raw_cast( 00381 mp::identity<T> tid, 00382 raw_ptr_templ&& rp 00383 ) 00384 { 00385 if(rp.audit_cast(tid)) 00386 { 00387 return do_raw_cast( 00388 tid, 00389 static_cast<raw_ptr_templ&&>(rp) 00390 ); 00391 } 00392 else return T(); 00393 } 00394 }; 00395 00396 template < 00397 typename T, 00398 class Auditor, 00399 class BadCastPolicy, 00400 typename BasePtrType 00401 > 00402 inline T raw_cast(raw_ptr_templ<Auditor, BadCastPolicy, BasePtrType>& a_ptr) 00403 { 00404 return audited_raw_cast(mp::identity<T>(), a_ptr); 00405 } 00406 00407 template < 00408 typename T, 00409 class Auditor, 00410 class BadCastPolicy, 00411 typename BasePtrType 00412 > 00413 inline T raw_cast( 00414 const raw_ptr_templ<Auditor, BadCastPolicy, BasePtrType>& a_ptr 00415 ) 00416 { 00417 return audited_raw_cast(mp::identity<T>(), a_ptr); 00418 } 00419 00420 template < 00421 typename T, 00422 class Auditor, 00423 class BadCastPolicy, 00424 typename BasePtrType 00425 > 00426 inline T raw_cast(raw_ptr_templ<Auditor, BadCastPolicy, BasePtrType>&& a_ptr) 00427 { 00428 return std::move(audited_raw_cast( 00429 mp::identity<T>(), 00430 std::move(a_ptr) 00431 )); 00432 } 00433 00434 // Declare the default type comparator and bad cast policy 00435 #ifndef MIRROR_FAST_RAW_PTR /* Debug mode */ 00436 00437 #if MIRROR_NO_RTTI 00438 typedef aux::int_seq_type_cmp default_type_cmp; 00439 #else 00440 typedef aux::type_info_cmp default_type_cmp; 00441 #endif 00442 00443 typedef aux::abort_at_bad_cast_policy default_bad_cast_policy; 00444 00445 #else /* Not debugging mode */ 00446 00447 #if MIRROR_NO_RTTI 00448 typedef aux::int_seq_type_cmp default_type_cmp; 00449 #else 00450 typedef aux::type_info_cmp default_type_cmp; 00451 #endif 00452 typedef aux::do_nothing_at_bad_cast_policy default_bad_cast_policy; 00453 00454 #endif 00455 // 00457 00466 typedef raw_ptr_templ< 00467 aux::ptr_cast_auditor<default_type_cmp>, 00468 default_bad_cast_policy, 00469 void* 00470 > raw_ptr; 00471 // 00472 // 00474 00483 typedef raw_ptr_templ< 00484 aux::ptr_cast_auditor<default_type_cmp>, 00485 default_bad_cast_policy, 00486 std::shared_ptr<void> 00487 > shared_raw_ptr; 00488 00489 // 00491 00500 typedef raw_ptr_templ< 00501 aux::ptr_cast_auditor<default_type_cmp>, 00502 default_bad_cast_policy, 00503 std::unique_ptr<void> 00504 > unique_raw_ptr; 00505 00506 MIRROR_NAMESPACE_END 00507 00508 #endif // BOOST_RAW_PTR_RAW_PTR_HPP