Jeff Thompson | a28eed8 | 2013-08-22 16:21:10 -0700 | [diff] [blame] | 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 <ndnboost/config.hpp> |
| 13 | # include <ndnboost/detail/workaround.hpp> |
| 14 | # include <ndnboost/mpl/int.hpp> |
| 15 | # include <ndnboost/type_traits/is_function.hpp> |
| 16 | # include <ndnboost/utility/enable_if.hpp> |
| 17 | |
| 18 | # if BOOST_WORKAROUND(BOOST_MSVC,>=1310) |
| 19 | # include <typeinfo> |
| 20 | # endif |
| 21 | |
| 22 | namespace ndnboost |
| 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 | { |
| 34 | __if_exists(the_counter<N + 256>) |
| 35 | { |
| 36 | BOOST_STATIC_CONSTANT(unsigned,count=(encode_counter<T,N + 257>::count)); |
| 37 | } |
| 38 | __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(*ndnboost::type_of::encode_index((ndnboost::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 | ndnboost::type_of::msvc_typeid_wrapper<typeid(ndnboost::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(ndnboost::type_of::typeof_register_type<name>(expr)))};\ |
| 198 | typedef typename ndnboost::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(ndnboost::type_of::typeof_register_type<name>(expr)))};\ |
| 205 | typedef ndnboost::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 | ndnboost::type_of::msvc_typeid_wrapper<sizeof(*ndnboost::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(ndnboost::type_of::typeof_register_type<name>(expr)));\ |
| 268 | typedef typename ndnboost::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(ndnboost::type_of::typeof_register_type<name>(expr)));\ |
| 275 | typedef ndnboost::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 |