member.hpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. /* Copyright 2003-2008 Joaquin M Lopez Munoz.
  2. * Distributed under the Boost Software License, Version 1.0.
  3. * (See accompanying file LICENSE_1_0.txt or copy at
  4. * http://www.boost.org/LICENSE_1_0.txt)
  5. *
  6. * See http://www.boost.org/libs/multi_index for library home page.
  7. */
  8. #ifndef BOOST_MULTI_INDEX_MEMBER_HPP
  9. #define BOOST_MULTI_INDEX_MEMBER_HPP
  10. #if defined(_MSC_VER)&&(_MSC_VER>=1200)
  11. #pragma once
  12. #endif
  13. #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
  14. #include <boost/mpl/if.hpp>
  15. #include <boost/type_traits/is_const.hpp>
  16. #include <boost/utility/enable_if.hpp>
  17. #include <cstddef>
  18. #if !defined(BOOST_NO_SFINAE)
  19. #include <boost/type_traits/is_convertible.hpp>
  20. #endif
  21. namespace boost{
  22. template<class T> class reference_wrapper; /* fwd decl. */
  23. namespace multi_index{
  24. namespace detail{
  25. /* member is a read/write key extractor for accessing a given
  26. * member of a class.
  27. * Additionally, member is overloaded to support referece_wrappers
  28. * of T and "chained pointers" to T's. By chained pointer to T we mean
  29. * a type P such that, given a p of Type P
  30. * *...n...*x is convertible to T&, for some n>=1.
  31. * Examples of chained pointers are raw and smart pointers, iterators and
  32. * arbitrary combinations of these (vg. T** or auto_ptr<T*>.)
  33. */
  34. /* NB. Some overloads of operator() have an extra dummy parameter int=0.
  35. * This disambiguator serves several purposes:
  36. * - Without it, MSVC++ 6.0 incorrectly regards some overloads as
  37. * specializations of a previous member function template.
  38. * - MSVC++ 6.0/7.0 seem to incorrectly treat some different memfuns
  39. * as if they have the same signature.
  40. * - If remove_const is broken due to lack of PTS, int=0 avoids the
  41. * declaration of memfuns with identical signature.
  42. */
  43. template<class Class,typename Type,Type Class::*PtrToMember>
  44. struct const_member_base
  45. {
  46. typedef Type result_type;
  47. template<typename ChainedPtr>
  48. #if !defined(BOOST_NO_SFINAE)
  49. typename disable_if<
  50. is_convertible<const ChainedPtr&,const Class&>,Type&>::type
  51. #else
  52. Type&
  53. #endif
  54. operator()(const ChainedPtr& x)const
  55. {
  56. return operator()(*x);
  57. }
  58. Type& operator()(const Class& x)const
  59. {
  60. return x.*PtrToMember;
  61. }
  62. Type& operator()(const reference_wrapper<const Class>& x)const
  63. {
  64. return operator()(x.get());
  65. }
  66. Type& operator()(const reference_wrapper<Class>& x,int=0)const
  67. {
  68. return operator()(x.get());
  69. }
  70. };
  71. template<class Class,typename Type,Type Class::*PtrToMember>
  72. struct non_const_member_base
  73. {
  74. typedef Type result_type;
  75. template<typename ChainedPtr>
  76. #if !defined(BOOST_NO_SFINAE)
  77. typename disable_if<
  78. is_convertible<const ChainedPtr&,const Class&>,Type&>::type
  79. #else
  80. Type&
  81. #endif
  82. operator()(const ChainedPtr& x)const
  83. {
  84. return operator()(*x);
  85. }
  86. const Type& operator()(const Class& x,int=0)const
  87. {
  88. return x.*PtrToMember;
  89. }
  90. Type& operator()(Class& x)const
  91. {
  92. return x.*PtrToMember;
  93. }
  94. const Type& operator()(const reference_wrapper<const Class>& x,int=0)const
  95. {
  96. return operator()(x.get());
  97. }
  98. Type& operator()(const reference_wrapper<Class>& x)const
  99. {
  100. return operator()(x.get());
  101. }
  102. };
  103. } /* namespace multi_index::detail */
  104. template<class Class,typename Type,Type Class::*PtrToMember>
  105. struct member:
  106. mpl::if_c<
  107. is_const<Type>::value,
  108. detail::const_member_base<Class,Type,PtrToMember>,
  109. detail::non_const_member_base<Class,Type,PtrToMember>
  110. >::type
  111. {
  112. };
  113. namespace detail{
  114. /* MSVC++ 6.0 does not support properly pointers to members as
  115. * non-type template arguments, as reported in
  116. * http://support.microsoft.com/default.aspx?scid=kb;EN-US;249045
  117. * A similar problem (though not identical) is shown by MSVC++ 7.0.
  118. * We provide an alternative to member<> accepting offsets instead
  119. * of pointers to members. This happens to work even for non-POD
  120. * types (although the standard forbids use of offsetof on these),
  121. * so it serves as a workaround in this compiler for all practical
  122. * purposes.
  123. * Surprisingly enough, other compilers, like Intel C++ 7.0/7.1 and
  124. * Visual Age 6.0, have similar bugs. This replacement of member<>
  125. * can be used for them too.
  126. */
  127. template<class Class,typename Type,std::size_t OffsetOfMember>
  128. struct const_member_offset_base
  129. {
  130. typedef Type result_type;
  131. template<typename ChainedPtr>
  132. #if !defined(BOOST_NO_SFINAE)
  133. typename disable_if<
  134. is_convertible<const ChainedPtr&,const Class&>,Type&>::type
  135. #else
  136. Type&
  137. #endif
  138. operator()(const ChainedPtr& x)const
  139. {
  140. return operator()(*x);
  141. }
  142. Type& operator()(const Class& x)const
  143. {
  144. return *static_cast<const Type*>(
  145. static_cast<const void*>(
  146. static_cast<const char*>(
  147. static_cast<const void *>(&x))+OffsetOfMember));
  148. }
  149. Type& operator()(const reference_wrapper<const Class>& x)const
  150. {
  151. return operator()(x.get());
  152. }
  153. Type& operator()(const reference_wrapper<Class>& x,int=0)const
  154. {
  155. return operator()(x.get());
  156. }
  157. };
  158. template<class Class,typename Type,std::size_t OffsetOfMember>
  159. struct non_const_member_offset_base
  160. {
  161. typedef Type result_type;
  162. template<typename ChainedPtr>
  163. #if !defined(BOOST_NO_SFINAE)
  164. typename disable_if<
  165. is_convertible<const ChainedPtr&,const Class&>,Type&>::type
  166. #else
  167. Type&
  168. #endif
  169. operator()(const ChainedPtr& x)const
  170. {
  171. return operator()(*x);
  172. }
  173. const Type& operator()(const Class& x,int=0)const
  174. {
  175. return *static_cast<const Type*>(
  176. static_cast<const void*>(
  177. static_cast<const char*>(
  178. static_cast<const void *>(&x))+OffsetOfMember));
  179. }
  180. Type& operator()(Class& x)const
  181. {
  182. return *static_cast<Type*>(
  183. static_cast<void*>(
  184. static_cast<char*>(static_cast<void *>(&x))+OffsetOfMember));
  185. }
  186. const Type& operator()(const reference_wrapper<const Class>& x,int=0)const
  187. {
  188. return operator()(x.get());
  189. }
  190. Type& operator()(const reference_wrapper<Class>& x)const
  191. {
  192. return operator()(x.get());
  193. }
  194. };
  195. } /* namespace multi_index::detail */
  196. template<class Class,typename Type,std::size_t OffsetOfMember>
  197. struct member_offset:
  198. mpl::if_c<
  199. is_const<Type>::value,
  200. detail::const_member_offset_base<Class,Type,OffsetOfMember>,
  201. detail::non_const_member_offset_base<Class,Type,OffsetOfMember>
  202. >::type
  203. {
  204. };
  205. /* BOOST_MULTI_INDEX_MEMBER resolves to member in the normal cases,
  206. * and to member_offset as a workaround in those defective compilers for
  207. * which BOOST_NO_POINTER_TO_MEMBER_TEMPLATE_PARAMETERS is defined.
  208. */
  209. #if defined(BOOST_NO_POINTER_TO_MEMBER_TEMPLATE_PARAMETERS)
  210. #define BOOST_MULTI_INDEX_MEMBER(Class,Type,MemberName) \
  211. ::boost::multi_index::member_offset< Class,Type,offsetof(Class,MemberName) >
  212. #else
  213. #define BOOST_MULTI_INDEX_MEMBER(Class,Type,MemberName) \
  214. ::boost::multi_index::member< Class,Type,&Class::MemberName >
  215. #endif
  216. } /* namespace multi_index */
  217. } /* namespace boost */
  218. #endif