has_xxx.hpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. #ifndef BOOST_MPL_HAS_XXX_HPP_INCLUDED
  2. #define BOOST_MPL_HAS_XXX_HPP_INCLUDED
  3. // Copyright Aleksey Gurtovoy 2002-2006
  4. // Copyright David Abrahams 2002-2003
  5. //
  6. // Distributed under the Boost Software License, Version 1.0.
  7. // (See accompanying file LICENSE_1_0.txt or copy at
  8. // http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. // See http://www.boost.org/libs/mpl for documentation.
  11. // $Id: has_xxx.hpp 49273 2008-10-11 06:54:06Z agurtovoy $
  12. // $Date: 2008-10-11 02:54:06 -0400 (Sat, 11 Oct 2008) $
  13. // $Revision: 49273 $
  14. #include <boost/mpl/bool.hpp>
  15. #include <boost/mpl/aux_/type_wrapper.hpp>
  16. #include <boost/mpl/aux_/yes_no.hpp>
  17. #include <boost/mpl/aux_/config/has_xxx.hpp>
  18. #include <boost/mpl/aux_/config/msvc_typename.hpp>
  19. #include <boost/mpl/aux_/config/msvc.hpp>
  20. #include <boost/mpl/aux_/config/static_constant.hpp>
  21. #include <boost/mpl/aux_/config/workaround.hpp>
  22. #include <boost/preprocessor/cat.hpp>
  23. #if BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT(0x590) )
  24. # include <boost/type_traits/is_class.hpp>
  25. #endif
  26. #if !defined(BOOST_MPL_CFG_NO_HAS_XXX)
  27. # if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
  28. // agurt, 11/sep/02: MSVC-specific version (< 7.1), based on a USENET
  29. // newsgroup's posting by John Madsen (comp.lang.c++.moderated,
  30. // 1999-11-12 19:17:06 GMT); the code is _not_ standard-conforming, but
  31. // it works way more reliably than the SFINAE-based implementation
  32. // Modified dwa 8/Oct/02 to handle reference types.
  33. # include <boost/mpl/if.hpp>
  34. # include <boost/mpl/bool.hpp>
  35. namespace boost { namespace mpl { namespace aux {
  36. struct has_xxx_tag;
  37. #if BOOST_WORKAROUND(BOOST_MSVC, == 1300)
  38. template< typename U > struct msvc_incomplete_array
  39. {
  40. typedef char (&type)[sizeof(U) + 1];
  41. };
  42. #endif
  43. template< typename T >
  44. struct msvc_is_incomplete
  45. {
  46. // MSVC is capable of some kinds of SFINAE. If U is an incomplete
  47. // type, it won't pick the second overload
  48. static char tester(...);
  49. #if BOOST_WORKAROUND(BOOST_MSVC, == 1300)
  50. template< typename U >
  51. static typename msvc_incomplete_array<U>::type tester(type_wrapper<U>);
  52. #else
  53. template< typename U >
  54. static char (& tester(type_wrapper<U>) )[sizeof(U)+1];
  55. #endif
  56. BOOST_STATIC_CONSTANT(bool, value =
  57. sizeof(tester(type_wrapper<T>())) == 1
  58. );
  59. };
  60. template<>
  61. struct msvc_is_incomplete<int>
  62. {
  63. BOOST_STATIC_CONSTANT(bool, value = false);
  64. };
  65. }}}
  66. # define BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF_(trait, name, default_) \
  67. template< typename T, typename name = ::boost::mpl::aux::has_xxx_tag > \
  68. struct BOOST_PP_CAT(trait,_impl) : T \
  69. { \
  70. static boost::mpl::aux::no_tag \
  71. test(void(*)(::boost::mpl::aux::has_xxx_tag)); \
  72. \
  73. static boost::mpl::aux::yes_tag test(...); \
  74. \
  75. BOOST_STATIC_CONSTANT(bool, value = \
  76. sizeof(test(static_cast<void(*)(name)>(0))) \
  77. != sizeof(boost::mpl::aux::no_tag) \
  78. ); \
  79. typedef boost::mpl::bool_<value> type; \
  80. }; \
  81. \
  82. template< typename T, typename fallback_ = boost::mpl::bool_<default_> > \
  83. struct trait \
  84. : boost::mpl::if_c< \
  85. boost::mpl::aux::msvc_is_incomplete<T>::value \
  86. , boost::mpl::bool_<false> \
  87. , BOOST_PP_CAT(trait,_impl)<T> \
  88. >::type \
  89. { \
  90. }; \
  91. \
  92. BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, void) \
  93. BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, bool) \
  94. BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, char) \
  95. BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, signed char) \
  96. BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, unsigned char) \
  97. BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, signed short) \
  98. BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, unsigned short) \
  99. BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, signed int) \
  100. BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, unsigned int) \
  101. BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, signed long) \
  102. BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, unsigned long) \
  103. BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, float) \
  104. BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, double) \
  105. BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, long double) \
  106. /**/
  107. # define BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, T) \
  108. template<> struct trait<T> \
  109. { \
  110. BOOST_STATIC_CONSTANT(bool, value = false); \
  111. typedef boost::mpl::bool_<false> type; \
  112. }; \
  113. /**/
  114. #if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
  115. # define BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(trait, name, unused) \
  116. BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF_(trait, name, unused) \
  117. BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, wchar_t) \
  118. /**/
  119. #else
  120. # define BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(trait, name, unused) \
  121. BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF_(trait, name, unused) \
  122. /**/
  123. #endif
  124. // SFINAE-based implementations below are derived from a USENET newsgroup's
  125. // posting by Rani Sharoni (comp.lang.c++.moderated, 2002-03-17 07:45:09 PST)
  126. # elif BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1400)) \
  127. || BOOST_WORKAROUND(__IBMCPP__, <= 700)
  128. // MSVC 7.1+ & VACPP
  129. // agurt, 15/jun/05: replace overload-based SFINAE implementation with SFINAE
  130. // applied to partial specialization to fix some apparently random failures
  131. // (thanks to Daniel Wallin for researching this!)
  132. # define BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(trait, name, default_) \
  133. template< typename T > \
  134. struct BOOST_PP_CAT(trait, _msvc_sfinae_helper) \
  135. { \
  136. typedef void type; \
  137. };\
  138. \
  139. template< typename T, typename U = void > \
  140. struct BOOST_PP_CAT(trait,_impl_) \
  141. { \
  142. BOOST_STATIC_CONSTANT(bool, value = false); \
  143. typedef boost::mpl::bool_<value> type; \
  144. }; \
  145. \
  146. template< typename T > \
  147. struct BOOST_PP_CAT(trait,_impl_)< \
  148. T \
  149. , typename BOOST_PP_CAT(trait, _msvc_sfinae_helper)< typename T::name >::type \
  150. > \
  151. { \
  152. BOOST_STATIC_CONSTANT(bool, value = true); \
  153. typedef boost::mpl::bool_<value> type; \
  154. }; \
  155. \
  156. template< typename T, typename fallback_ = boost::mpl::bool_<default_> > \
  157. struct trait \
  158. : BOOST_PP_CAT(trait,_impl_)<T> \
  159. { \
  160. }; \
  161. /**/
  162. # elif BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT(0x590) )
  163. # define BOOST_MPL_HAS_XXX_TRAIT_NAMED_BCB_DEF(trait, trait_tester, name, default_) \
  164. template< typename T, bool IS_CLASS > \
  165. struct trait_tester \
  166. { \
  167. BOOST_STATIC_CONSTANT( bool, value = false ); \
  168. }; \
  169. template< typename T > \
  170. struct trait_tester< T, true > \
  171. { \
  172. struct trait_tester_impl \
  173. { \
  174. template < class U > \
  175. static int resolve( boost::mpl::aux::type_wrapper<U> const volatile * \
  176. , boost::mpl::aux::type_wrapper<typename U::name >* = 0 ); \
  177. static char resolve( ... ); \
  178. }; \
  179. typedef boost::mpl::aux::type_wrapper<T> t_; \
  180. BOOST_STATIC_CONSTANT( bool, value = ( sizeof( trait_tester_impl::resolve( static_cast< t_ * >(0) ) ) == sizeof(int) ) ); \
  181. }; \
  182. template< typename T, typename fallback_ = boost::mpl::bool_<default_> > \
  183. struct trait \
  184. { \
  185. BOOST_STATIC_CONSTANT( bool, value = (trait_tester< T, boost::is_class< T >::value >::value) ); \
  186. typedef boost::mpl::bool_< trait< T, fallback_ >::value > type; \
  187. };
  188. # define BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(trait, name, default_) \
  189. BOOST_MPL_HAS_XXX_TRAIT_NAMED_BCB_DEF( trait \
  190. , BOOST_PP_CAT(trait,_tester) \
  191. , name \
  192. , default_ ) \
  193. /**/
  194. # else // other SFINAE-capable compilers
  195. # define BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(trait, name, default_) \
  196. template< typename T, typename fallback_ = boost::mpl::bool_<default_> > \
  197. struct trait \
  198. { \
  199. struct gcc_3_2_wknd \
  200. { \
  201. template< typename U > \
  202. static boost::mpl::aux::yes_tag test( \
  203. boost::mpl::aux::type_wrapper<U> const volatile* \
  204. , boost::mpl::aux::type_wrapper<BOOST_MSVC_TYPENAME U::name>* = 0 \
  205. ); \
  206. \
  207. static boost::mpl::aux::no_tag test(...); \
  208. }; \
  209. \
  210. typedef boost::mpl::aux::type_wrapper<T> t_; \
  211. BOOST_STATIC_CONSTANT(bool, value = \
  212. sizeof(gcc_3_2_wknd::test(static_cast<t_*>(0))) \
  213. == sizeof(boost::mpl::aux::yes_tag) \
  214. ); \
  215. typedef boost::mpl::bool_<value> type; \
  216. }; \
  217. /**/
  218. # endif // BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
  219. #else // BOOST_MPL_CFG_NO_HAS_XXX
  220. // placeholder implementation
  221. # define BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(trait, name, default_) \
  222. template< typename T, typename fallback_ = boost::mpl::bool_<default_> > \
  223. struct trait \
  224. { \
  225. BOOST_STATIC_CONSTANT(bool, value = fallback_::value); \
  226. typedef fallback_ type; \
  227. }; \
  228. /**/
  229. #endif
  230. #define BOOST_MPL_HAS_XXX_TRAIT_DEF(name) \
  231. BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(BOOST_PP_CAT(has_,name), name, false) \
  232. /**/
  233. #endif // BOOST_MPL_HAS_XXX_HPP_INCLUDED