Mirror reflection library 0.5.13

mirror/raw_ptr/raw_ptr.hpp

Go to the documentation of this file.
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

Copyright © 2006-2011 Matus Chochlik, University of Zilina, Zilina, Slovakia.
<matus.chochlik -at- fri.uniza.sk>
<chochlik -at -gmail.com>
Documentation generated on Fri Dec 16 2011 by Doxygen (version 1.7.3).
Important note: Although the 'boostified' version of Mirror uses the Boost C++ libraries Coding Guidelines and is implemented inside of the boost namespace, it IS NOT an officially reviewed and accepted Boost library. Mirror is being developed with the intention to be submitted for review for inclusion to the Boost C++ libraries.