global_fun.hpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  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_GLOBAL_FUN_HPP
  9. #define BOOST_MULTI_INDEX_GLOBAL_FUN_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/type_traits/is_reference.hpp>
  17. #include <boost/type_traits/remove_const.hpp>
  18. #include <boost/type_traits/remove_reference.hpp>
  19. #include <boost/utility/enable_if.hpp>
  20. #if !defined(BOOST_NO_SFINAE)
  21. #include <boost/type_traits/is_convertible.hpp>
  22. #endif
  23. namespace boost{
  24. template<class T> class reference_wrapper; /* fwd decl. */
  25. namespace multi_index{
  26. namespace detail{
  27. /* global_fun is a read-only key extractor from Value based on a given global
  28. * (or static member) function with signature:
  29. *
  30. * Type f([const] Value [&]);
  31. *
  32. * Additionally, global_fun and const_global_fun are overloaded to support
  33. * referece_wrappers of Value and "chained pointers" to Value's. By chained
  34. * pointer to T we mean a type P such that, given a p of Type P
  35. * *...n...*x is convertible to T&, for some n>=1.
  36. * Examples of chained pointers are raw and smart pointers, iterators and
  37. * arbitrary combinations of these (vg. T** or auto_ptr<T*>.)
  38. */
  39. /* NB. Some overloads of operator() have an extra dummy parameter int=0.
  40. * This disambiguator serves several purposes:
  41. * - Without it, MSVC++ 6.0 incorrectly regards some overloads as
  42. * specializations of a previous member function template.
  43. * - MSVC++ 6.0/7.0 seem to incorrectly treat some different memfuns
  44. * as if they have the same signature.
  45. * - If remove_const is broken due to lack of PTS, int=0 avoids the
  46. * declaration of memfuns with identical signature.
  47. */
  48. template<class Value,typename Type,Type (*PtrToFunction)(Value)>
  49. struct const_ref_global_fun_base
  50. {
  51. typedef typename remove_reference<Type>::type result_type;
  52. template<typename ChainedPtr>
  53. #if !defined(BOOST_NO_SFINAE)
  54. typename disable_if<
  55. is_convertible<const ChainedPtr&,Value>,Type>::type
  56. #else
  57. Type
  58. #endif
  59. operator()(const ChainedPtr& x)const
  60. {
  61. return operator()(*x);
  62. }
  63. Type operator()(Value x)const
  64. {
  65. return PtrToFunction(x);
  66. }
  67. Type operator()(
  68. const reference_wrapper<
  69. typename remove_reference<Value>::type>& x)const
  70. {
  71. return operator()(x.get());
  72. }
  73. Type operator()(
  74. const reference_wrapper<
  75. typename remove_const<
  76. typename remove_reference<Value>::type>::type>& x,int=0)const
  77. {
  78. return operator()(x.get());
  79. }
  80. };
  81. template<class Value,typename Type,Type (*PtrToFunction)(Value)>
  82. struct non_const_ref_global_fun_base
  83. {
  84. typedef typename remove_reference<Type>::type result_type;
  85. template<typename ChainedPtr>
  86. #if !defined(BOOST_NO_SFINAE)
  87. typename disable_if<
  88. is_convertible<ChainedPtr&,Value>,Type>::type
  89. #else
  90. Type
  91. #endif
  92. operator()(const ChainedPtr& x)const
  93. {
  94. return operator()(*x);
  95. }
  96. Type operator()(Value x)const
  97. {
  98. return PtrToFunction(x);
  99. }
  100. Type operator()(
  101. const reference_wrapper<
  102. typename remove_reference<Value>::type>& x)const
  103. {
  104. return operator()(x.get());
  105. }
  106. };
  107. template<class Value,typename Type,Type (*PtrToFunction)(Value)>
  108. struct non_ref_global_fun_base
  109. {
  110. typedef typename remove_reference<Type>::type result_type;
  111. template<typename ChainedPtr>
  112. #if !defined(BOOST_NO_SFINAE)
  113. typename disable_if<
  114. is_convertible<const ChainedPtr&,const Value&>,Type>::type
  115. #else
  116. Type
  117. #endif
  118. operator()(const ChainedPtr& x)const
  119. {
  120. return operator()(*x);
  121. }
  122. Type operator()(const Value& x)const
  123. {
  124. return PtrToFunction(x);
  125. }
  126. Type operator()(const reference_wrapper<const Value>& x)const
  127. {
  128. return operator()(x.get());
  129. }
  130. Type operator()(
  131. const reference_wrapper<
  132. typename remove_const<Value>::type>& x,int=0)const
  133. {
  134. return operator()(x.get());
  135. }
  136. };
  137. } /* namespace multi_index::detail */
  138. template<class Value,typename Type,Type (*PtrToFunction)(Value)>
  139. struct global_fun:
  140. mpl::if_c<
  141. is_reference<Value>::value,
  142. typename mpl::if_c<
  143. is_const<typename remove_reference<Value>::type>::value,
  144. detail::const_ref_global_fun_base<Value,Type,PtrToFunction>,
  145. detail::non_const_ref_global_fun_base<Value,Type,PtrToFunction>
  146. >::type,
  147. detail::non_ref_global_fun_base<Value,Type,PtrToFunction>
  148. >::type
  149. {
  150. };
  151. } /* namespace multi_index */
  152. } /* namespace boost */
  153. #endif