Chris@101: /* Copyright 2003-2013 Joaquin M Lopez Munoz. Chris@16: * Distributed under the Boost Software License, Version 1.0. Chris@16: * (See accompanying file LICENSE_1_0.txt or copy at Chris@16: * http://www.boost.org/LICENSE_1_0.txt) Chris@16: * Chris@16: * See http://www.boost.org/libs/multi_index for library home page. Chris@16: */ Chris@16: Chris@16: #ifndef BOOST_MULTI_INDEX_MEM_FUN_HPP Chris@16: #define BOOST_MULTI_INDEX_MEM_FUN_HPP Chris@16: Chris@101: #if defined(_MSC_VER) Chris@16: #pragma once Chris@16: #endif Chris@16: Chris@16: #include /* keep it first to prevent nasty warns in MSVC */ Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #if !defined(BOOST_NO_SFINAE) Chris@16: #include Chris@16: #endif Chris@16: Chris@16: namespace boost{ Chris@16: Chris@16: template class reference_wrapper; /* fwd decl. */ Chris@16: Chris@16: namespace multi_index{ Chris@16: Chris@16: /* mem_fun implements a read-only key extractor based on a given non-const Chris@16: * member function of a class. Chris@16: * const_mem_fun does the same for const member functions. Chris@16: * Additionally, mem_fun and const_mem_fun are overloaded to support Chris@16: * referece_wrappers of T and "chained pointers" to T's. By chained pointer Chris@16: * to T we mean a type P such that, given a p of Type P Chris@16: * *...n...*x is convertible to T&, for some n>=1. Chris@16: * Examples of chained pointers are raw and smart pointers, iterators and Chris@16: * arbitrary combinations of these (vg. T** or auto_ptr.) Chris@16: */ Chris@16: Chris@16: template Chris@16: struct const_mem_fun Chris@16: { Chris@16: typedef typename remove_reference::type result_type; Chris@16: Chris@16: template Chris@16: Chris@16: #if !defined(BOOST_NO_SFINAE) Chris@16: typename disable_if< Chris@16: is_convertible,Type>::type Chris@16: #else Chris@16: Type Chris@16: #endif Chris@16: Chris@16: operator()(const ChainedPtr& x)const Chris@16: { Chris@16: return operator()(*x); Chris@16: } Chris@16: Chris@16: Type operator()(const Class& x)const Chris@16: { Chris@16: return (x.*PtrToMemberFunction)(); Chris@16: } Chris@16: Chris@16: Type operator()(const reference_wrapper& x)const Chris@16: { Chris@16: return operator()(x.get()); Chris@16: } Chris@16: Chris@16: Type operator()(const reference_wrapper& x)const Chris@16: { Chris@16: return operator()(x.get()); Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct mem_fun Chris@16: { Chris@16: typedef typename remove_reference::type result_type; Chris@16: Chris@16: template Chris@16: Chris@16: #if !defined(BOOST_NO_SFINAE) Chris@16: typename disable_if< Chris@16: is_convertible,Type>::type Chris@16: #else Chris@16: Type Chris@16: #endif Chris@16: Chris@16: operator()(const ChainedPtr& x)const Chris@16: { Chris@16: return operator()(*x); Chris@16: } Chris@16: Chris@16: Type operator()(Class& x)const Chris@16: { Chris@16: return (x.*PtrToMemberFunction)(); Chris@16: } Chris@16: Chris@16: Type operator()(const reference_wrapper& x)const Chris@16: { Chris@16: return operator()(x.get()); Chris@16: } Chris@16: }; Chris@16: Chris@16: /* MSVC++ 6.0 has problems with const member functions as non-type template Chris@16: * parameters, somehow it takes them as non-const. const_mem_fun_explicit Chris@16: * workarounds this deficiency by accepting an extra type parameter that Chris@16: * specifies the signature of the member function. The workaround was found at: Chris@16: * Daniel, C.:"Re: weird typedef problem in VC", Chris@16: * news:microsoft.public.vc.language, 21st nov 2002, Chris@16: * http://groups.google.com/groups? Chris@16: * hl=en&lr=&ie=UTF-8&selm=ukwvg3O0BHA.1512%40tkmsftngp05 Chris@101: * Chris@101: * MSVC++ 6.0 support has been dropped and [const_]mem_fun_explicit is Chris@101: * deprecated. Chris@16: */ Chris@16: Chris@16: template< Chris@16: class Class,typename Type, Chris@16: typename PtrToMemberFunctionType,PtrToMemberFunctionType PtrToMemberFunction> Chris@16: struct const_mem_fun_explicit Chris@16: { Chris@16: typedef typename remove_reference::type result_type; Chris@16: Chris@16: template Chris@16: Chris@16: #if !defined(BOOST_NO_SFINAE) Chris@16: typename disable_if< Chris@16: is_convertible,Type>::type Chris@16: #else Chris@16: Type Chris@16: #endif Chris@16: Chris@16: operator()(const ChainedPtr& x)const Chris@16: { Chris@16: return operator()(*x); Chris@16: } Chris@16: Chris@16: Type operator()(const Class& x)const Chris@16: { Chris@16: return (x.*PtrToMemberFunction)(); Chris@16: } Chris@16: Chris@16: Type operator()(const reference_wrapper& x)const Chris@16: { Chris@16: return operator()(x.get()); Chris@16: } Chris@16: Chris@16: Type operator()(const reference_wrapper& x)const Chris@16: { Chris@16: return operator()(x.get()); Chris@16: } Chris@16: }; Chris@16: Chris@16: template< Chris@16: class Class,typename Type, Chris@16: typename PtrToMemberFunctionType,PtrToMemberFunctionType PtrToMemberFunction> Chris@16: struct mem_fun_explicit Chris@16: { Chris@16: typedef typename remove_reference::type result_type; Chris@16: Chris@16: template Chris@16: Chris@16: #if !defined(BOOST_NO_SFINAE) Chris@16: typename disable_if< Chris@16: is_convertible,Type>::type Chris@16: #else Chris@16: Type Chris@16: #endif Chris@16: Chris@16: operator()(const ChainedPtr& x)const Chris@16: { Chris@16: return operator()(*x); Chris@16: } Chris@16: Chris@16: Type operator()(Class& x)const Chris@16: { Chris@16: return (x.*PtrToMemberFunction)(); Chris@16: } Chris@16: Chris@16: Type operator()(const reference_wrapper& x)const Chris@16: { Chris@16: return operator()(x.get()); Chris@16: } Chris@16: }; Chris@16: Chris@101: /* BOOST_MULTI_INDEX_CONST_MEM_FUN and BOOST_MULTI_INDEX_MEM_FUN used to Chris@101: * resolve to [const_]mem_fun_explicit for MSVC++ 6.0 and to Chris@101: * [const_]mem_fun otherwise. Support for this compiler having been dropped, Chris@101: * they are now just wrappers over [const_]mem_fun kept for backwards- Chris@101: * compatibility reasons. Chris@16: */ Chris@16: Chris@16: #define BOOST_MULTI_INDEX_CONST_MEM_FUN(Class,Type,MemberFunName) \ Chris@16: ::boost::multi_index::const_mem_fun< Class,Type,&Class::MemberFunName > Chris@16: #define BOOST_MULTI_INDEX_MEM_FUN(Class,Type,MemberFunName) \ Chris@16: ::boost::multi_index::mem_fun< Class,Type,&Class::MemberFunName > Chris@16: Chris@16: } /* namespace multi_index */ Chris@16: Chris@16: } /* namespace boost */ Chris@16: Chris@16: #endif