typeof_impl.hpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. // Copyright (C) 2005 Igor Chesnokov, mailto:ichesnokov@gmail.com (VC 6.5,VC 7.1 + counter code)
  2. // Copyright (C) 2005-2007 Peder Holt (VC 7.0 + framework)
  3. // Copyright (C) 2006 Steven Watanabe (VC 8.0)
  4. // Use, modification and distribution is subject to the Boost Software
  5. // License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt)
  6. #ifndef BOOST_TYPEOF_MSVC_TYPEOF_IMPL_HPP_INCLUDED
  7. # define BOOST_TYPEOF_MSVC_TYPEOF_IMPL_HPP_INCLUDED
  8. # include <boost/config.hpp>
  9. # include <boost/config/workaround.hpp>
  10. # include <boost/typeof/constant.hpp>
  11. # include <boost/type_traits/enable_if.hpp>
  12. # include <boost/type_traits/is_function.hpp>
  13. # include <typeinfo>
  14. namespace boost
  15. {
  16. namespace type_of
  17. {
  18. //Compile time constant code
  19. # if defined(_MSC_EXTENSIONS)
  20. template<int N> struct the_counter;
  21. template<typename T,int N = 5/*for similarity*/>
  22. struct encode_counter
  23. {
  24. __if_exists(the_counter<N + 256>)
  25. {
  26. BOOST_STATIC_CONSTANT(unsigned,count=(encode_counter<T,N + 257>::count));
  27. }
  28. __if_not_exists(the_counter<N + 256>)
  29. {
  30. __if_exists(the_counter<N + 64>)
  31. {
  32. BOOST_STATIC_CONSTANT(unsigned,count=(encode_counter<T,N + 65>::count));
  33. }
  34. __if_not_exists(the_counter<N + 64>)
  35. {
  36. __if_exists(the_counter<N + 16>)
  37. {
  38. BOOST_STATIC_CONSTANT(unsigned,count=(encode_counter<T,N + 17>::count));
  39. }
  40. __if_not_exists(the_counter<N + 16>)
  41. {
  42. __if_exists(the_counter<N + 4>)
  43. {
  44. BOOST_STATIC_CONSTANT(unsigned,count=(encode_counter<T,N + 5>::count));
  45. }
  46. __if_not_exists(the_counter<N + 4>)
  47. {
  48. __if_exists(the_counter<N>)
  49. {
  50. BOOST_STATIC_CONSTANT(unsigned,count=(encode_counter<T,N + 1>::count));
  51. }
  52. __if_not_exists(the_counter<N>)
  53. {
  54. BOOST_STATIC_CONSTANT(unsigned,count=N);
  55. typedef the_counter<N> type;
  56. }
  57. }
  58. }
  59. }
  60. }
  61. };
  62. # define BOOST_TYPEOF_INDEX(T) (encode_counter<T>::count)
  63. # define BOOST_TYPEOF_NEXT_INDEX(next)
  64. # else
  65. template<int N> struct encode_counter : encode_counter<N - 1> {};
  66. template<> struct encode_counter<0> {};
  67. //Need to default to a larger value than 4, as due to MSVC's ETI errors. (sizeof(int)==4)
  68. char (*encode_index(...))[5];
  69. # define BOOST_TYPEOF_INDEX(T) (sizeof(*boost::type_of::encode_index((boost::type_of::encode_counter<1005>*)0)))
  70. # define BOOST_TYPEOF_NEXT_INDEX(next) friend char (*encode_index(encode_counter<next>*))[next];
  71. # endif
  72. //Typeof code
  73. # if BOOST_WORKAROUND(BOOST_MSVC,>=1400)
  74. struct msvc_extract_type_default_param {};
  75. template<typename ID, typename T = msvc_extract_type_default_param>
  76. struct msvc_extract_type;
  77. template<typename ID>
  78. struct msvc_extract_type<ID, msvc_extract_type_default_param> {
  79. template<bool>
  80. struct id2type_impl;
  81. typedef id2type_impl<true> id2type;
  82. };
  83. template<typename ID, typename T>
  84. struct msvc_extract_type : msvc_extract_type<ID,msvc_extract_type_default_param>
  85. {
  86. template<>
  87. struct id2type_impl<true> //VC8.0 specific bugfeature
  88. {
  89. typedef T type;
  90. };
  91. template<bool>
  92. struct id2type_impl;
  93. typedef id2type_impl<true> id2type;
  94. };
  95. template<typename T, typename ID>
  96. struct msvc_register_type : msvc_extract_type<ID, T>
  97. {
  98. };
  99. # else
  100. template<typename ID>
  101. struct msvc_extract_type
  102. {
  103. struct id2type;
  104. };
  105. template<typename T, typename ID>
  106. struct msvc_register_type : msvc_extract_type<ID>
  107. {
  108. typedef msvc_extract_type<ID> base_type;
  109. struct base_type::id2type // This uses nice VC6.5 and VC7.1 bugfeature
  110. {
  111. typedef T type;
  112. };
  113. };
  114. # endif
  115. template<int ID>
  116. struct msvc_typeid_wrapper {
  117. typedef typename msvc_extract_type<constant<int,ID> >::id2type id2type;
  118. typedef typename id2type::type type;
  119. };
  120. //Workaround for ETI-bug for VC6 and VC7
  121. template<>
  122. struct msvc_typeid_wrapper<1> {
  123. typedef msvc_typeid_wrapper<1> type;
  124. };
  125. //Workaround for ETI-bug for VC7.1
  126. template<>
  127. struct msvc_typeid_wrapper<4> {
  128. typedef msvc_typeid_wrapper<4> type;
  129. };
  130. //Tie it all together
  131. template<typename T>
  132. struct encode_type
  133. {
  134. //Get the next available compile time constants index
  135. BOOST_STATIC_CONSTANT(unsigned,value=BOOST_TYPEOF_INDEX(T));
  136. //Instantiate the template
  137. typedef typename msvc_register_type<T,constant<int,value> >::id2type type;
  138. //Set the next compile time constants index
  139. BOOST_STATIC_CONSTANT(unsigned,next=value+1);
  140. //Increment the compile time constant (only needed when extensions are not active
  141. BOOST_TYPEOF_NEXT_INDEX(next);
  142. };
  143. template<class T>
  144. struct sizer
  145. {
  146. typedef char(*type)[encode_type<T>::value];
  147. };
  148. template<typename T> typename enable_if_<
  149. !is_function<T>::value,
  150. typename sizer<T>::type>::type encode_start(T const&);
  151. template<typename T> typename enable_if_<
  152. is_function<T>::value,
  153. typename sizer<T>::type>::type encode_start(T&);
  154. template<typename Organizer, typename T>
  155. msvc_register_type<T,Organizer> typeof_register_type(const T&,Organizer* =0);
  156. # define BOOST_TYPEOF(expr) \
  157. boost::type_of::msvc_typeid_wrapper<sizeof(*boost::type_of::encode_start(expr))>::type
  158. # define BOOST_TYPEOF_TPL(expr) typename BOOST_TYPEOF(expr)
  159. # define BOOST_TYPEOF_NESTED_TYPEDEF_TPL(name,expr) \
  160. struct name {\
  161. enum {_typeof_register_value=sizeof(boost::type_of::typeof_register_type<name>(expr))};\
  162. typedef typename boost::type_of::msvc_extract_type<name>::id2type id2type;\
  163. typedef typename id2type::type type;\
  164. };
  165. # define BOOST_TYPEOF_NESTED_TYPEDEF(name,expr) \
  166. struct name {\
  167. enum {_typeof_register_value=sizeof(boost::type_of::typeof_register_type<name>(expr))};\
  168. typedef boost::type_of::msvc_extract_type<name>::id2type id2type;\
  169. typedef id2type::type type;\
  170. };
  171. }
  172. }
  173. #endif//BOOST_TYPEOF_MSVC_TYPEOF_IMPL_HPP_INCLUDED