member.hpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. /* Copyright 2003-2015 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)
  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 unique_ptr<T*>.)
  33. */
  34. template<class Class,typename Type,Type Class::*PtrToMember>
  35. struct const_member_base
  36. {
  37. typedef Type result_type;
  38. template<typename ChainedPtr>
  39. #if !defined(BOOST_NO_SFINAE)
  40. typename disable_if<
  41. is_convertible<const ChainedPtr&,const Class&>,Type&>::type
  42. #else
  43. Type&
  44. #endif
  45. operator()(const ChainedPtr& x)const
  46. {
  47. return operator()(*x);
  48. }
  49. Type& operator()(const Class& x)const
  50. {
  51. return x.*PtrToMember;
  52. }
  53. Type& operator()(const reference_wrapper<const Class>& x)const
  54. {
  55. return operator()(x.get());
  56. }
  57. Type& operator()(const reference_wrapper<Class>& x)const
  58. {
  59. return operator()(x.get());
  60. }
  61. };
  62. template<class Class,typename Type,Type Class::*PtrToMember>
  63. struct non_const_member_base
  64. {
  65. typedef Type result_type;
  66. template<typename ChainedPtr>
  67. #if !defined(BOOST_NO_SFINAE)
  68. typename disable_if<
  69. is_convertible<const ChainedPtr&,const Class&>,Type&>::type
  70. #else
  71. Type&
  72. #endif
  73. operator()(const ChainedPtr& x)const
  74. {
  75. return operator()(*x);
  76. }
  77. const Type& operator()(const Class& x)const
  78. {
  79. return x.*PtrToMember;
  80. }
  81. Type& operator()(Class& x)const
  82. {
  83. return x.*PtrToMember;
  84. }
  85. const Type& operator()(const reference_wrapper<const Class>& x)const
  86. {
  87. return operator()(x.get());
  88. }
  89. Type& operator()(const reference_wrapper<Class>& x)const
  90. {
  91. return operator()(x.get());
  92. }
  93. };
  94. } /* namespace multi_index::detail */
  95. template<class Class,typename Type,Type Class::*PtrToMember>
  96. struct member:
  97. mpl::if_c<
  98. is_const<Type>::value,
  99. detail::const_member_base<Class,Type,PtrToMember>,
  100. detail::non_const_member_base<Class,Type,PtrToMember>
  101. >::type
  102. {
  103. };
  104. namespace detail{
  105. /* MSVC++ 6.0 does not support properly pointers to members as
  106. * non-type template arguments, as reported in
  107. * http://support.microsoft.com/default.aspx?scid=kb;EN-US;249045
  108. * A similar problem (though not identical) is shown by MSVC++ 7.0.
  109. * We provide an alternative to member<> accepting offsets instead
  110. * of pointers to members. This happens to work even for non-POD
  111. * types (although the standard forbids use of offsetof on these),
  112. * so it serves as a workaround in this compiler for all practical
  113. * purposes.
  114. * Surprisingly enough, other compilers, like Intel C++ 7.0/7.1 and
  115. * Visual Age 6.0, have similar bugs. This replacement of member<>
  116. * can be used for them too.
  117. *
  118. * Support for such old compilers is dropped and
  119. * [non_]const_member_offset_base is deprecated.
  120. */
  121. template<class Class,typename Type,std::size_t OffsetOfMember>
  122. struct const_member_offset_base
  123. {
  124. typedef Type result_type;
  125. template<typename ChainedPtr>
  126. #if !defined(BOOST_NO_SFINAE)
  127. typename disable_if<
  128. is_convertible<const ChainedPtr&,const Class&>,Type&>::type
  129. #else
  130. Type&
  131. #endif
  132. operator()(const ChainedPtr& x)const
  133. {
  134. return operator()(*x);
  135. }
  136. Type& operator()(const Class& x)const
  137. {
  138. return *static_cast<const Type*>(
  139. static_cast<const void*>(
  140. static_cast<const char*>(
  141. static_cast<const void *>(&x))+OffsetOfMember));
  142. }
  143. Type& operator()(const reference_wrapper<const Class>& x)const
  144. {
  145. return operator()(x.get());
  146. }
  147. Type& operator()(const reference_wrapper<Class>& x)const
  148. {
  149. return operator()(x.get());
  150. }
  151. };
  152. template<class Class,typename Type,std::size_t OffsetOfMember>
  153. struct non_const_member_offset_base
  154. {
  155. typedef Type result_type;
  156. template<typename ChainedPtr>
  157. #if !defined(BOOST_NO_SFINAE)
  158. typename disable_if<
  159. is_convertible<const ChainedPtr&,const Class&>,Type&>::type
  160. #else
  161. Type&
  162. #endif
  163. operator()(const ChainedPtr& x)const
  164. {
  165. return operator()(*x);
  166. }
  167. const Type& operator()(const Class& x)const
  168. {
  169. return *static_cast<const Type*>(
  170. static_cast<const void*>(
  171. static_cast<const char*>(
  172. static_cast<const void *>(&x))+OffsetOfMember));
  173. }
  174. Type& operator()(Class& x)const
  175. {
  176. return *static_cast<Type*>(
  177. static_cast<void*>(
  178. static_cast<char*>(static_cast<void *>(&x))+OffsetOfMember));
  179. }
  180. const Type& operator()(const reference_wrapper<const Class>& x)const
  181. {
  182. return operator()(x.get());
  183. }
  184. Type& operator()(const reference_wrapper<Class>& x)const
  185. {
  186. return operator()(x.get());
  187. }
  188. };
  189. } /* namespace multi_index::detail */
  190. template<class Class,typename Type,std::size_t OffsetOfMember>
  191. struct member_offset:
  192. mpl::if_c<
  193. is_const<Type>::value,
  194. detail::const_member_offset_base<Class,Type,OffsetOfMember>,
  195. detail::non_const_member_offset_base<Class,Type,OffsetOfMember>
  196. >::type
  197. {
  198. };
  199. /* BOOST_MULTI_INDEX_MEMBER resolves to member in the normal cases,
  200. * and to member_offset as a workaround in those defective compilers for
  201. * which BOOST_NO_POINTER_TO_MEMBER_TEMPLATE_PARAMETERS is defined.
  202. */
  203. #if defined(BOOST_NO_POINTER_TO_MEMBER_TEMPLATE_PARAMETERS)
  204. #define BOOST_MULTI_INDEX_MEMBER(Class,Type,MemberName) \
  205. ::boost::multi_index::member_offset< Class,Type,offsetof(Class,MemberName) >
  206. #else
  207. #define BOOST_MULTI_INDEX_MEMBER(Class,Type,MemberName) \
  208. ::boost::multi_index::member< Class,Type,&Class::MemberName >
  209. #endif
  210. } /* namespace multi_index */
  211. } /* namespace boost */
  212. #endif