1 /* Copyright 2003-2019 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_MEM_FUN_HPP 10 #define BOOST_MULTI_INDEX_MEM_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/mpl/if.hpp> 18 #include <boost/type_traits/remove_reference.hpp> 19 #include <boost/utility/enable_if.hpp> 20 21 #if !defined(BOOST_NO_SFINAE) 22 #include <boost/type_traits/is_convertible.hpp> 23 #endif 24 25 namespace boost{ 26 27 template<class T> class reference_wrapper; /* fwd decl. */ 28 29 namespace multi_index{ 30 31 /* mem_fun implements a read-only key extractor based on a given non-const 32 * member function of a class. 33 * Also, the following variations are provided: 34 * const_mem_fun: const member functions 35 * volatile_mem_fun: volatile member functions 36 * cv_mem_fun: const volatile member functions 37 * ref_mem_fun: ref-qualifed member functions (C++11) 38 * cref_mem_fun: const ref-qualifed member functions (C++11) 39 * vref_mem_fun: volatile ref-qualifed member functions (C++11) 40 * cvref_mem_fun: const volatile ref-qualifed member functions (C++11) 41 * 42 * All of these classes are overloaded to support boost::referece_wrappers 43 * of T and "chained pointers" to T's. By chained pointer to T we mean a type 44 * 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 namespace detail{ 51 52 template< 53 class Class,typename Type, 54 typename PtrToMemberFunctionType,PtrToMemberFunctionType PtrToMemberFunction 55 > 56 struct const_mem_fun_impl 57 { 58 typedef typename remove_reference<Type>::type result_type; 59 60 template<typename ChainedPtr> 61 62 #if !defined(BOOST_NO_SFINAE) 63 typename disable_if< 64 is_convertible<const ChainedPtr&,const Class&>,Type>::type 65 #else 66 Type 67 #endif 68 operator ()boost::multi_index::detail::const_mem_fun_impl69 operator()(const ChainedPtr& x)const 70 { 71 return operator()(*x); 72 } 73 operator ()boost::multi_index::detail::const_mem_fun_impl74 Type operator()(const Class& x)const 75 { 76 return (x.*PtrToMemberFunction)(); 77 } 78 operator ()boost::multi_index::detail::const_mem_fun_impl79 Type operator()(const reference_wrapper<const Class>& x)const 80 { 81 return operator()(x.get()); 82 } 83 operator ()boost::multi_index::detail::const_mem_fun_impl84 Type operator()(const reference_wrapper<Class>& x)const 85 { 86 return operator()(x.get()); 87 } 88 }; 89 90 template< 91 class Class,typename Type, 92 typename PtrToMemberFunctionType,PtrToMemberFunctionType PtrToMemberFunction 93 > 94 struct mem_fun_impl 95 { 96 typedef typename remove_reference<Type>::type result_type; 97 98 template<typename ChainedPtr> 99 100 #if !defined(BOOST_NO_SFINAE) 101 typename disable_if< 102 is_convertible<ChainedPtr&,Class&>,Type>::type 103 #else 104 Type 105 #endif 106 operator ()boost::multi_index::detail::mem_fun_impl107 operator()(const ChainedPtr& x)const 108 { 109 return operator()(*x); 110 } 111 operator ()boost::multi_index::detail::mem_fun_impl112 Type operator()(Class& x)const 113 { 114 return (x.*PtrToMemberFunction)(); 115 } 116 operator ()boost::multi_index::detail::mem_fun_impl117 Type operator()(const reference_wrapper<Class>& x)const 118 { 119 return operator()(x.get()); 120 } 121 }; 122 123 } /* namespace multi_index::detail */ 124 125 template<class Class,typename Type,Type (Class::*PtrToMemberFunction)()const> 126 struct const_mem_fun:detail::const_mem_fun_impl< 127 Class,Type,Type (Class::*)()const,PtrToMemberFunction 128 >{}; 129 130 template< 131 class Class,typename Type, 132 Type (Class::*PtrToMemberFunction)()const volatile 133 > 134 struct cv_mem_fun:detail::const_mem_fun_impl< 135 Class,Type,Type (Class::*)()const volatile,PtrToMemberFunction 136 >{}; 137 138 template<class Class,typename Type,Type (Class::*PtrToMemberFunction)()> 139 struct mem_fun: 140 detail::mem_fun_impl<Class,Type,Type (Class::*)(),PtrToMemberFunction>{}; 141 142 template< 143 class Class,typename Type,Type (Class::*PtrToMemberFunction)()volatile 144 > 145 struct volatile_mem_fun:detail::mem_fun_impl< 146 Class,Type,Type (Class::*)()volatile,PtrToMemberFunction 147 >{}; 148 149 #if !defined(BOOST_NO_CXX11_REF_QUALIFIERS) 150 151 template< 152 class Class,typename Type,Type (Class::*PtrToMemberFunction)()const& 153 > 154 struct cref_mem_fun:detail::const_mem_fun_impl< 155 Class,Type,Type (Class::*)()const&,PtrToMemberFunction 156 >{}; 157 158 template< 159 class Class,typename Type, 160 Type (Class::*PtrToMemberFunction)()const volatile& 161 > 162 struct cvref_mem_fun:detail::const_mem_fun_impl< 163 Class,Type,Type (Class::*)()const volatile&,PtrToMemberFunction 164 >{}; 165 166 template<class Class,typename Type,Type (Class::*PtrToMemberFunction)()&> 167 struct ref_mem_fun: 168 detail::mem_fun_impl<Class,Type,Type (Class::*)()&,PtrToMemberFunction>{}; 169 170 template< 171 class Class,typename Type,Type (Class::*PtrToMemberFunction)()volatile& 172 > 173 struct vref_mem_fun:detail::mem_fun_impl< 174 Class,Type,Type (Class::*)()volatile&,PtrToMemberFunction 175 >{}; 176 177 #endif 178 179 /* MSVC++ 6.0 has problems with const member functions as non-type template 180 * parameters, somehow it takes them as non-const. const_mem_fun_explicit 181 * workarounds this deficiency by accepting an extra type parameter that 182 * specifies the signature of the member function. The workaround was found at: 183 * Daniel, C.:"Re: weird typedef problem in VC", 184 * news:microsoft.public.vc.language, 21st nov 2002, 185 * http://groups.google.com/groups? 186 * hl=en&lr=&ie=UTF-8&selm=ukwvg3O0BHA.1512%40tkmsftngp05 187 * 188 * MSVC++ 6.0 support has been dropped and [const_]mem_fun_explicit is 189 * deprecated. 190 */ 191 192 template< 193 class Class,typename Type, 194 typename PtrToMemberFunctionType,PtrToMemberFunctionType PtrToMemberFunction 195 > 196 struct const_mem_fun_explicit 197 { 198 typedef typename remove_reference<Type>::type result_type; 199 200 template<typename ChainedPtr> 201 202 #if !defined(BOOST_NO_SFINAE) 203 typename disable_if< 204 is_convertible<const ChainedPtr&,const Class&>,Type>::type 205 #else 206 Type 207 #endif 208 operator ()boost::multi_index::const_mem_fun_explicit209 operator()(const ChainedPtr& x)const 210 { 211 return operator()(*x); 212 } 213 operator ()boost::multi_index::const_mem_fun_explicit214 Type operator()(const Class& x)const 215 { 216 return (x.*PtrToMemberFunction)(); 217 } 218 operator ()boost::multi_index::const_mem_fun_explicit219 Type operator()(const reference_wrapper<const Class>& x)const 220 { 221 return operator()(x.get()); 222 } 223 operator ()boost::multi_index::const_mem_fun_explicit224 Type operator()(const reference_wrapper<Class>& x)const 225 { 226 return operator()(x.get()); 227 } 228 }; 229 230 template< 231 class Class,typename Type, 232 typename PtrToMemberFunctionType,PtrToMemberFunctionType PtrToMemberFunction 233 > 234 struct mem_fun_explicit 235 { 236 typedef typename remove_reference<Type>::type result_type; 237 238 template<typename ChainedPtr> 239 240 #if !defined(BOOST_NO_SFINAE) 241 typename disable_if< 242 is_convertible<ChainedPtr&,Class&>,Type>::type 243 #else 244 Type 245 #endif 246 operator ()boost::multi_index::mem_fun_explicit247 operator()(const ChainedPtr& x)const 248 { 249 return operator()(*x); 250 } 251 operator ()boost::multi_index::mem_fun_explicit252 Type operator()(Class& x)const 253 { 254 return (x.*PtrToMemberFunction)(); 255 } 256 operator ()boost::multi_index::mem_fun_explicit257 Type operator()(const reference_wrapper<Class>& x)const 258 { 259 return operator()(x.get()); 260 } 261 }; 262 263 /* BOOST_MULTI_INDEX_CONST_MEM_FUN and BOOST_MULTI_INDEX_MEM_FUN used to 264 * resolve to [const_]mem_fun_explicit for MSVC++ 6.0 and to 265 * [const_]mem_fun otherwise. Support for this compiler having been dropped, 266 * they are now just wrappers over [const_]mem_fun kept for backwards- 267 * compatibility reasons. 268 */ 269 270 #define BOOST_MULTI_INDEX_CONST_MEM_FUN(Class,Type,MemberFunName) \ 271 ::boost::multi_index::const_mem_fun< Class,Type,&Class::MemberFunName > 272 #define BOOST_MULTI_INDEX_MEM_FUN(Class,Type,MemberFunName) \ 273 ::boost::multi_index::mem_fun< Class,Type,&Class::MemberFunName > 274 275 } /* namespace multi_index */ 276 277 } /* namespace boost */ 278 279 #endif 280