1 2 // Copyright (C) 2005 Igor Chesnokov, mailto:ichesnokov@gmail.com (VC 6.5,VC 7.1 + counter code) 3 // Copyright (C) 2005-2007 Peder Holt (VC 7.0 + framework) 4 // Copyright (C) 2006 Steven Watanabe (VC 8.0) 5 6 // Use, modification and distribution is subject to the Boost Software 7 // License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) 8 9 #ifndef BOOST_TYPEOF_MSVC_TYPEOF_IMPL_HPP_INCLUDED 10 # define BOOST_TYPEOF_MSVC_TYPEOF_IMPL_HPP_INCLUDED 11 12 # include <boost/config.hpp> 13 # include <boost/detail/workaround.hpp> 14 # include <boost/mpl/int.hpp> 15 # include <boost/type_traits/is_function.hpp> 16 # include <boost/utility/enable_if.hpp> 17 18 # if BOOST_WORKAROUND(BOOST_MSVC,>=1310) 19 # include <typeinfo> 20 # endif 21 22 namespace boost 23 { 24 namespace type_of 25 { 26 27 //Compile time constant code 28 # if BOOST_WORKAROUND(BOOST_MSVC,>=1300) && defined(_MSC_EXTENSIONS) 29 template<int N> struct the_counter; 30 31 template<typename T,int N = 5/*for similarity*/> 32 struct encode_counter 33 { __if_existsboost::type_of::encode_counter34 __if_exists(the_counter<N + 256>) 35 { 36 BOOST_STATIC_CONSTANT(unsigned,count=(encode_counter<T,N + 257>::count)); 37 } __if_not_existsboost::type_of::encode_counter38 __if_not_exists(the_counter<N + 256>) 39 { 40 __if_exists(the_counter<N + 64>) 41 { 42 BOOST_STATIC_CONSTANT(unsigned,count=(encode_counter<T,N + 65>::count)); 43 } 44 __if_not_exists(the_counter<N + 64>) 45 { 46 __if_exists(the_counter<N + 16>) 47 { 48 BOOST_STATIC_CONSTANT(unsigned,count=(encode_counter<T,N + 17>::count)); 49 } 50 __if_not_exists(the_counter<N + 16>) 51 { 52 __if_exists(the_counter<N + 4>) 53 { 54 BOOST_STATIC_CONSTANT(unsigned,count=(encode_counter<T,N + 5>::count)); 55 } 56 __if_not_exists(the_counter<N + 4>) 57 { 58 __if_exists(the_counter<N>) 59 { 60 BOOST_STATIC_CONSTANT(unsigned,count=(encode_counter<T,N + 1>::count)); 61 } 62 __if_not_exists(the_counter<N>) 63 { 64 BOOST_STATIC_CONSTANT(unsigned,count=N); 65 typedef the_counter<N> type; 66 } 67 } 68 } 69 } 70 } 71 }; 72 73 # define BOOST_TYPEOF_INDEX(T) (encode_counter<T>::count) 74 # define BOOST_TYPEOF_NEXT_INDEX(next) 75 # else 76 template<int N> struct encode_counter : encode_counter<N - 1> {}; 77 template<> struct encode_counter<0> {}; 78 79 //Need to default to a larger value than 4, as due to MSVC's ETI errors. (sizeof(int)==4) 80 char (*encode_index(...))[5]; 81 82 # define BOOST_TYPEOF_INDEX(T) (sizeof(*boost::type_of::encode_index((boost::type_of::encode_counter<1005>*)0))) 83 # define BOOST_TYPEOF_NEXT_INDEX(next) friend char (*encode_index(encode_counter<next>*))[next]; 84 # endif 85 86 //Typeof code 87 88 # if BOOST_WORKAROUND(BOOST_MSVC,==1300) 89 template<typename ID> 90 struct msvc_extract_type 91 { 92 template<bool> 93 struct id2type_impl; 94 95 typedef id2type_impl<true> id2type; 96 }; 97 98 template<typename T, typename ID> 99 struct msvc_register_type : msvc_extract_type<ID> 100 { 101 template<> 102 struct id2type_impl<true> //VC7.0 specific bugfeature 103 { 104 typedef T type; 105 }; 106 }; 107 #elif BOOST_WORKAROUND(BOOST_MSVC,>=1400) 108 struct msvc_extract_type_default_param {}; 109 110 template<typename ID, typename T = msvc_extract_type_default_param> 111 struct msvc_extract_type; 112 113 template<typename ID> 114 struct msvc_extract_type<ID, msvc_extract_type_default_param> { 115 template<bool> 116 struct id2type_impl; 117 118 typedef id2type_impl<true> id2type; 119 }; 120 121 template<typename ID, typename T> 122 struct msvc_extract_type : msvc_extract_type<ID,msvc_extract_type_default_param> 123 { 124 template<> 125 struct id2type_impl<true> //VC8.0 specific bugfeature 126 { 127 typedef T type; 128 }; 129 template<bool> 130 struct id2type_impl; 131 132 typedef id2type_impl<true> id2type; 133 }; 134 135 template<typename T, typename ID> 136 struct msvc_register_type : msvc_extract_type<ID, T> 137 { 138 }; 139 # else 140 template<typename ID> 141 struct msvc_extract_type 142 { 143 struct id2type; 144 }; 145 146 template<typename T, typename ID> 147 struct msvc_register_type : msvc_extract_type<ID> 148 { 149 typedef msvc_extract_type<ID> base_type; 150 struct base_type::id2type // This uses nice VC6.5 and VC7.1 bugfeature 151 { 152 typedef T type; 153 }; 154 }; 155 # endif 156 // EAN: preprocess this block out on advice of Peder Holt 157 // to eliminate errors in type_traits/common_type.hpp 158 # if 0 //BOOST_WORKAROUND(BOOST_MSVC,==1310) 159 template<const std::type_info& ref_type_info> 160 struct msvc_typeid_wrapper { 161 typedef typename msvc_extract_type<msvc_typeid_wrapper>::id2type id2type; 162 typedef typename id2type::type wrapped_type; 163 typedef typename wrapped_type::type type; 164 }; 165 //This class is used for registering the type T. encode_type<T> is mapped against typeid(encode_type<T>). 166 //msvc_typeid_wrapper<typeid(encode_type<T>)> will now have a type typedef that equals encode_type<T>. 167 template<typename T> 168 struct encode_type 169 { 170 typedef encode_type<T> input_type; 171 //Invoke registration of encode_type<T>. typeid(encode_type<T>) is now mapped to encode_type<T>. Do not use registered_type for anything. 172 //The reason for registering encode_type<T> rather than T, is that VC handles typeid(function reference) poorly. By adding another 173 //level of indirection, we solve this problem. 174 typedef typename msvc_register_type<input_type,msvc_typeid_wrapper<typeid(input_type)> >::id2type registered_type; 175 typedef T type; 176 }; 177 178 template<typename T> typename disable_if< 179 typename is_function<T>::type, 180 typename encode_type<T>::input_type>::type encode_start(T const&); 181 182 template<typename T> typename enable_if< 183 typename is_function<T>::type, 184 typename encode_type<T>::input_type>::type encode_start(T&); 185 186 template<typename Organizer, typename T> 187 msvc_register_type<T,Organizer> typeof_register_type(const T&); 188 189 190 # define BOOST_TYPEOF(expr) \ 191 boost::type_of::msvc_typeid_wrapper<typeid(boost::type_of::encode_start(expr))>::type 192 193 # define BOOST_TYPEOF_TPL(expr) typename BOOST_TYPEOF(expr) 194 195 # define BOOST_TYPEOF_NESTED_TYPEDEF_TPL(name,expr) \ 196 struct name {\ 197 enum {_typeof_register_value=sizeof(typeid(boost::type_of::typeof_register_type<name>(expr)))};\ 198 typedef typename boost::type_of::msvc_extract_type<name>::id2type id2type;\ 199 typedef typename id2type::type type;\ 200 }; 201 202 # define BOOST_TYPEOF_NESTED_TYPEDEF(name,expr) \ 203 struct name {\ 204 enum {_typeof_register_value=sizeof(typeid(boost::type_of::typeof_register_type<name>(expr)))};\ 205 typedef boost::type_of::msvc_extract_type<name>::id2type id2type;\ 206 typedef id2type::type type;\ 207 }; 208 209 # else 210 template<int ID> 211 struct msvc_typeid_wrapper { 212 typedef typename msvc_extract_type<mpl::int_<ID> >::id2type id2type; 213 typedef typename id2type::type type; 214 }; 215 //Workaround for ETI-bug for VC6 and VC7 216 template<> 217 struct msvc_typeid_wrapper<1> { 218 typedef msvc_typeid_wrapper<1> type; 219 }; 220 //Workaround for ETI-bug for VC7.1 221 template<> 222 struct msvc_typeid_wrapper<4> { 223 typedef msvc_typeid_wrapper<4> type; 224 }; 225 226 //Tie it all together 227 template<typename T> 228 struct encode_type 229 { 230 //Get the next available compile time constants index 231 BOOST_STATIC_CONSTANT(unsigned,value=BOOST_TYPEOF_INDEX(T)); 232 //Instantiate the template 233 typedef typename msvc_register_type<T,mpl::int_<value> >::id2type type; 234 //Set the next compile time constants index 235 BOOST_STATIC_CONSTANT(unsigned,next=value+1); 236 //Increment the compile time constant (only needed when extensions are not active 237 BOOST_TYPEOF_NEXT_INDEX(next); 238 }; 239 240 template<class T> 241 struct sizer 242 { 243 typedef char(*type)[encode_type<T>::value]; 244 }; 245 # if BOOST_WORKAROUND(BOOST_MSVC,>=1310) 246 template<typename T> typename disable_if< 247 typename is_function<T>::type, 248 typename sizer<T>::type>::type encode_start(T const&); 249 250 template<typename T> typename enable_if< 251 typename is_function<T>::type, 252 typename sizer<T>::type>::type encode_start(T&); 253 # else 254 template<typename T> 255 typename sizer<T>::type encode_start(T const&); 256 # endif 257 template<typename Organizer, typename T> 258 msvc_register_type<T,Organizer> typeof_register_type(const T&,Organizer* =0); 259 260 # define BOOST_TYPEOF(expr) \ 261 boost::type_of::msvc_typeid_wrapper<sizeof(*boost::type_of::encode_start(expr))>::type 262 263 # define BOOST_TYPEOF_TPL(expr) typename BOOST_TYPEOF(expr) 264 265 # define BOOST_TYPEOF_NESTED_TYPEDEF_TPL(name,expr) \ 266 struct name {\ 267 BOOST_STATIC_CONSTANT(int,_typeof_register_value=sizeof(boost::type_of::typeof_register_type<name>(expr)));\ 268 typedef typename boost::type_of::msvc_extract_type<name>::id2type id2type;\ 269 typedef typename id2type::type type;\ 270 }; 271 272 # define BOOST_TYPEOF_NESTED_TYPEDEF(name,expr) \ 273 struct name {\ 274 BOOST_STATIC_CONSTANT(int,_typeof_register_value=sizeof(boost::type_of::typeof_register_type<name>(expr)));\ 275 typedef boost::type_of::msvc_extract_type<name>::id2type id2type;\ 276 typedef id2type::type type;\ 277 }; 278 279 #endif 280 } 281 } 282 283 #endif//BOOST_TYPEOF_MSVC_TYPEOF_IMPL_HPP_INCLUDED 284