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 9 #ifndef BOOST_MULTI_INDEX_GLOBAL_FUN_HPP 10 #define BOOST_MULTI_INDEX_GLOBAL_FUN_HPP 11 12 #if defined(_MSC_VER) 13 #pragma once 14 #endif 15 16 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ 17 #include <boost/detail/workaround.hpp> 18 #include <boost/mpl/if.hpp> 19 #include <boost/type_traits/is_const.hpp> 20 #include <boost/type_traits/is_reference.hpp> 21 #include <boost/type_traits/remove_const.hpp> 22 #include <boost/type_traits/remove_reference.hpp> 23 #include <boost/utility/enable_if.hpp> 24 25 #if !defined(BOOST_NO_SFINAE) 26 #include <boost/type_traits/is_convertible.hpp> 27 #endif 28 29 namespace boost{ 30 31 template<class T> class reference_wrapper; /* fwd decl. */ 32 33 namespace multi_index{ 34 35 namespace detail{ 36 37 /* global_fun is a read-only key extractor from Value based on a given global 38 * (or static member) function with signature: 39 * 40 * Type f([const] Value [&]); 41 * 42 * Additionally, global_fun and const_global_fun are overloaded to support 43 * referece_wrappers of Value and "chained pointers" to Value's. By chained 44 * pointer to T we mean a type P such that, given a p of Type P 45 * *...n...*x is convertible to T&, for some n>=1. 46 * Examples of chained pointers are raw and smart pointers, iterators and 47 * arbitrary combinations of these (vg. T** or unique_ptr<T*>.) 48 */ 49 50 template<class Value,typename Type,Type (*PtrToFunction)(Value)> 51 struct const_ref_global_fun_base 52 { 53 typedef typename remove_reference<Type>::type result_type; 54 55 template<typename ChainedPtr> 56 57 #if !defined(BOOST_NO_SFINAE) 58 typename disable_if< 59 is_convertible<const ChainedPtr&,Value>,Type>::type 60 #else 61 Type 62 #endif 63 operator ()boost::multi_index::detail::const_ref_global_fun_base64 operator()(const ChainedPtr& x)const 65 { 66 return operator()(*x); 67 } 68 operator ()boost::multi_index::detail::const_ref_global_fun_base69 Type operator()(Value x)const 70 { 71 return PtrToFunction(x); 72 } 73 operator ()boost::multi_index::detail::const_ref_global_fun_base74 Type operator()( 75 const reference_wrapper< 76 typename remove_reference<Value>::type>& x)const 77 { 78 return operator()(x.get()); 79 } 80 operator ()boost::multi_index::detail::const_ref_global_fun_base81 Type operator()( 82 const reference_wrapper< 83 typename remove_const< 84 typename remove_reference<Value>::type>::type>& x 85 86 #if BOOST_WORKAROUND(BOOST_MSVC,==1310) 87 /* http://lists.boost.org/Archives/boost/2015/10/226135.php */ 88 ,int=0 89 #endif 90 91 )const 92 { 93 return operator()(x.get()); 94 } 95 }; 96 97 template<class Value,typename Type,Type (*PtrToFunction)(Value)> 98 struct non_const_ref_global_fun_base 99 { 100 typedef typename remove_reference<Type>::type result_type; 101 102 template<typename ChainedPtr> 103 104 #if !defined(BOOST_NO_SFINAE) 105 typename disable_if< 106 is_convertible<ChainedPtr&,Value>,Type>::type 107 #else 108 Type 109 #endif 110 operator ()boost::multi_index::detail::non_const_ref_global_fun_base111 operator()(const ChainedPtr& x)const 112 { 113 return operator()(*x); 114 } 115 operator ()boost::multi_index::detail::non_const_ref_global_fun_base116 Type operator()(Value x)const 117 { 118 return PtrToFunction(x); 119 } 120 operator ()boost::multi_index::detail::non_const_ref_global_fun_base121 Type operator()( 122 const reference_wrapper< 123 typename remove_reference<Value>::type>& x)const 124 { 125 return operator()(x.get()); 126 } 127 }; 128 129 template<class Value,typename Type,Type (*PtrToFunction)(Value)> 130 struct non_ref_global_fun_base 131 { 132 typedef typename remove_reference<Type>::type result_type; 133 134 template<typename ChainedPtr> 135 136 #if !defined(BOOST_NO_SFINAE) 137 typename disable_if< 138 is_convertible<const ChainedPtr&,const Value&>,Type>::type 139 #else 140 Type 141 #endif 142 operator ()boost::multi_index::detail::non_ref_global_fun_base143 operator()(const ChainedPtr& x)const 144 { 145 return operator()(*x); 146 } 147 operator ()boost::multi_index::detail::non_ref_global_fun_base148 Type operator()(const Value& x)const 149 { 150 return PtrToFunction(x); 151 } 152 operator ()boost::multi_index::detail::non_ref_global_fun_base153 Type operator()(const reference_wrapper<const Value>& x)const 154 { 155 return operator()(x.get()); 156 } 157 operator ()boost::multi_index::detail::non_ref_global_fun_base158 Type operator()( 159 const reference_wrapper<typename remove_const<Value>::type>& x)const 160 { 161 return operator()(x.get()); 162 } 163 }; 164 165 } /* namespace multi_index::detail */ 166 167 template<class Value,typename Type,Type (*PtrToFunction)(Value)> 168 struct global_fun: 169 mpl::if_c< 170 is_reference<Value>::value, 171 typename mpl::if_c< 172 is_const<typename remove_reference<Value>::type>::value, 173 detail::const_ref_global_fun_base<Value,Type,PtrToFunction>, 174 detail::non_const_ref_global_fun_base<Value,Type,PtrToFunction> 175 >::type, 176 detail::non_ref_global_fun_base<Value,Type,PtrToFunction> 177 >::type 178 { 179 }; 180 181 } /* namespace multi_index */ 182 183 } /* namespace boost */ 184 185 #endif 186