00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00041 #ifndef UTIL_ACCESSCASTED_H
00042 #define UTIL_ACCESSCASTED_H
00043
00044 #include <boost/utility/enable_if.hpp>
00045 #include <boost/type_traits/remove_pointer.hpp>
00046 #include <boost/type_traits/remove_reference.hpp>
00047 #include <boost/type_traits/is_convertible.hpp>
00048 #include <boost/type_traits/is_polymorphic.hpp>
00049 #include <boost/type_traits/is_base_of.hpp>
00050
00051
00052
00053 namespace util {
00054 using boost::remove_pointer;
00055 using boost::remove_reference;
00056 using boost::is_convertible;
00057 using boost::is_polymorphic;
00058 using boost::is_base_of;
00059 using boost::enable_if;
00060
00061
00062 template <typename SRC, typename TAR>
00063 struct can_cast : boost::false_type {};
00064
00065 template <typename SRC, typename TAR>
00066 struct can_cast<SRC*,TAR*> { enum { value = is_base_of<SRC,TAR>::value };};
00067
00068 template <typename SRC, typename TAR>
00069 struct can_cast<SRC*&,TAR*> { enum { value = is_base_of<SRC,TAR>::value };};
00070
00071 template <typename SRC, typename TAR>
00072 struct can_cast<SRC&,TAR&> { enum { value = is_base_of<SRC,TAR>::value };};
00073
00074
00075 template <typename T>
00076 struct has_RTTI
00077 {
00078 typedef typename remove_pointer<
00079 typename remove_reference<T>::type>::type TPlain;
00080
00081 enum { value = is_polymorphic<TPlain>::value };
00082 };
00083
00084 template <typename SRC, typename TAR>
00085 struct use_dynamic_downcast
00086 {
00087 enum { value = can_cast<SRC,TAR>::value
00088 && has_RTTI<SRC>::value
00089 && has_RTTI<TAR>::value
00090 };
00091 };
00092
00093 template <typename SRC, typename TAR>
00094 struct use_static_downcast
00095 {
00096 enum { value = can_cast<SRC,TAR>::value
00097 && ( !has_RTTI<SRC>::value
00098 || !has_RTTI<TAR>::value
00099 )
00100 };
00101 };
00102
00103 template <typename SRC, typename TAR>
00104 struct use_conversion
00105 {
00106 enum { value = is_convertible<SRC,TAR>::value
00107 && !( use_static_downcast<SRC,TAR>::value
00108 ||use_dynamic_downcast<SRC,TAR>::value
00109 )
00110 };
00111 };
00112
00113
00114
00115 template<typename X>
00116 struct EmptyVal
00117 {
00118 static X create() { return X(); }
00119 };
00120 template<typename X>
00121 struct EmptyVal<X*&>
00122 {
00123 static X*& create() { static X* nullP(0); return nullP; }
00124 };
00125
00126
00127
00128
00129
00130 template<typename RET>
00131 struct NullAccessor
00132 {
00133 typedef RET Ret;
00134
00135 static RET access (...) { return ifEmpty(); }
00136 static RET ifEmpty () { return EmptyVal<RET>::create(); }
00137 };
00138
00139 template<typename TAR>
00140 struct AccessCasted : NullAccessor<TAR>
00141 {
00142 using NullAccessor<TAR>::access;
00143
00144 template<typename ELM>
00145 static typename enable_if< use_dynamic_downcast<ELM&,TAR>, TAR>::type
00146 access (ELM& elem)
00147 {
00148 return dynamic_cast<TAR> (elem);
00149 }
00150
00151 template<typename ELM>
00152 static typename enable_if< use_static_downcast<ELM&,TAR>, TAR>::type
00153 access (ELM& elem)
00154 {
00155 return static_cast<TAR> (elem);
00156 }
00157
00158 template<typename ELM>
00159 static typename enable_if< use_conversion<ELM&,TAR>, TAR>::type
00160 access (ELM& elem)
00161 {
00162 return elem;
00163 }
00164 };
00165
00166
00167 }
00168 #endif