sl@0: /* Copyright 2003-2006 Joaquín M López Muñoz. sl@0: * Distributed under the Boost Software License, Version 1.0. sl@0: * (See accompanying file LICENSE_1_0.txt or copy at sl@0: * http://www.boost.org/LICENSE_1_0.txt) sl@0: * sl@0: * See http://www.boost.org/libs/multi_index for library home page. sl@0: */ sl@0: sl@0: #ifndef BOOST_MULTI_INDEX_IDENTITY_HPP sl@0: #define BOOST_MULTI_INDEX_IDENTITY_HPP sl@0: sl@0: #if defined(_MSC_VER)&&(_MSC_VER>=1200) sl@0: #pragma once sl@0: #endif sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: #if !defined(BOOST_NO_SFINAE) sl@0: #include sl@0: #endif sl@0: sl@0: namespace boost{ sl@0: sl@0: template class reference_wrapper; /* fwd decl. */ sl@0: sl@0: namespace multi_index{ sl@0: sl@0: namespace detail{ sl@0: sl@0: /* identity is a do-nothing key extractor that returns the [const] Type& sl@0: * object passed. sl@0: * Additionally, identity is overloaded to support referece_wrappers sl@0: * of Type and "chained pointers" to Type's. By chained pointer to Type we sl@0: * mean a type P such that, given a p of type P sl@0: * *...n...*x is convertible to Type&, for some n>=1. sl@0: * Examples of chained pointers are raw and smart pointers, iterators and sl@0: * arbitrary combinations of these (vg. Type** or auto_ptr.) sl@0: */ sl@0: sl@0: /* NB. Some overloads of operator() have an extra dummy parameter int=0. sl@0: * This disambiguator serves several purposes: sl@0: * - Without it, MSVC++ 6.0 incorrectly regards some overloads as sl@0: * specializations of a previous member function template. sl@0: * - MSVC++ 6.0/7.0 seem to incorrectly treat some different memfuns sl@0: * as if they have the same signature. sl@0: * - If remove_const is broken due to lack of PTS, int=0 avoids the sl@0: * declaration of memfuns with identical signature. sl@0: */ sl@0: sl@0: template sl@0: struct const_identity_base sl@0: { sl@0: typedef Type result_type; sl@0: sl@0: template sl@0: sl@0: #if !defined(BOOST_NO_SFINAE) sl@0: typename disable_if,Type&>::type sl@0: #else sl@0: Type& sl@0: #endif sl@0: sl@0: operator()(const ChainedPtr& x)const sl@0: { sl@0: return operator()(*x); sl@0: } sl@0: sl@0: Type& operator()(Type& x)const sl@0: { sl@0: return x; sl@0: } sl@0: sl@0: Type& operator()(const reference_wrapper& x)const sl@0: { sl@0: return x.get(); sl@0: } sl@0: sl@0: Type& operator()( sl@0: const reference_wrapper::type>& x,int=0)const sl@0: { sl@0: return x.get(); sl@0: } sl@0: }; sl@0: sl@0: template sl@0: struct non_const_identity_base sl@0: { sl@0: typedef Type result_type; sl@0: sl@0: /* templatized for pointer-like types */ sl@0: sl@0: template sl@0: sl@0: #if !defined(BOOST_NO_SFINAE) sl@0: typename disable_if< sl@0: is_convertible,Type&>::type sl@0: #else sl@0: Type& sl@0: #endif sl@0: sl@0: operator()(const ChainedPtr& x)const sl@0: { sl@0: return operator()(*x); sl@0: } sl@0: sl@0: const Type& operator()(const Type& x,int=0)const sl@0: { sl@0: return x; sl@0: } sl@0: sl@0: Type& operator()(Type& x)const sl@0: { sl@0: return x; sl@0: } sl@0: sl@0: const Type& operator()(const reference_wrapper& x,int=0)const sl@0: { sl@0: return x.get(); sl@0: } sl@0: sl@0: Type& operator()(const reference_wrapper& x)const sl@0: { sl@0: return x.get(); sl@0: } sl@0: }; sl@0: sl@0: } /* namespace multi_index::detail */ sl@0: sl@0: template sl@0: struct identity: sl@0: mpl::if_c< sl@0: is_const::value, sl@0: detail::const_identity_base,detail::non_const_identity_base sl@0: >::type sl@0: { sl@0: }; sl@0: sl@0: } /* namespace multi_index */ sl@0: sl@0: } /* namespace boost */ sl@0: sl@0: #endif