global_fun.hpp 4.3 KB

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