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_IDENTITY_HPP 10 #define BOOST_MULTI_INDEX_IDENTITY_HPP 11 12 #if defined(_MSC_VER) 13 #pragma once 14 #endif 15 16 #include <boost/config.hpp> 17 #include <boost/detail/workaround.hpp> 18 #include <boost/mpl/if.hpp> 19 #include <boost/multi_index/identity_fwd.hpp> 20 #include <boost/type_traits/is_const.hpp> 21 #include <boost/type_traits/remove_const.hpp> 22 #include <boost/utility/enable_if.hpp> 23 24 #if !defined(BOOST_NO_SFINAE) 25 #include <boost/type_traits/is_convertible.hpp> 26 #endif 27 28 namespace boost{ 29 30 template<class Type> class reference_wrapper; /* fwd decl. */ 31 32 namespace multi_index{ 33 34 namespace detail{ 35 36 /* identity is a do-nothing key extractor that returns the [const] Type& 37 * object passed. 38 * Additionally, identity is overloaded to support referece_wrappers 39 * of Type and "chained pointers" to Type's. By chained pointer to Type we 40 * mean a type P such that, given a p of type P 41 * *...n...*x is convertible to Type&, for some n>=1. 42 * Examples of chained pointers are raw and smart pointers, iterators and 43 * arbitrary combinations of these (vg. Type** or unique_ptr<Type*>.) 44 */ 45 46 template<typename Type> 47 struct const_identity_base 48 { 49 typedef Type result_type; 50 51 template<typename ChainedPtr> 52 53 #if !defined(BOOST_NO_SFINAE) 54 typename disable_if<is_convertible<const ChainedPtr&,Type&>,Type&>::type 55 #else 56 Type& 57 #endif 58 operator ()boost::multi_index::detail::const_identity_base59 operator()(const ChainedPtr& x)const 60 { 61 return operator()(*x); 62 } 63 operator ()boost::multi_index::detail::const_identity_base64 Type& operator()(Type& x)const 65 { 66 return x; 67 } 68 operator ()boost::multi_index::detail::const_identity_base69 Type& operator()(const reference_wrapper<Type>& x)const 70 { 71 return x.get(); 72 } 73 operator ()boost::multi_index::detail::const_identity_base74 Type& operator()( 75 const reference_wrapper<typename remove_const<Type>::type>& x 76 77 #if BOOST_WORKAROUND(BOOST_MSVC,==1310) 78 /* http://lists.boost.org/Archives/boost/2015/10/226135.php */ 79 ,int=0 80 #endif 81 82 )const 83 { 84 return x.get(); 85 } 86 }; 87 88 template<typename Type> 89 struct non_const_identity_base 90 { 91 typedef Type result_type; 92 93 /* templatized for pointer-like types */ 94 95 template<typename ChainedPtr> 96 97 #if !defined(BOOST_NO_SFINAE) 98 typename disable_if< 99 is_convertible<const ChainedPtr&,const Type&>,Type&>::type 100 #else 101 Type& 102 #endif 103 operator ()boost::multi_index::detail::non_const_identity_base104 operator()(const ChainedPtr& x)const 105 { 106 return operator()(*x); 107 } 108 operator ()boost::multi_index::detail::non_const_identity_base109 const Type& operator()(const Type& x)const 110 { 111 return x; 112 } 113 operator ()boost::multi_index::detail::non_const_identity_base114 Type& operator()(Type& x)const 115 { 116 return x; 117 } 118 operator ()boost::multi_index::detail::non_const_identity_base119 const Type& operator()(const reference_wrapper<const Type>& x)const 120 { 121 return x.get(); 122 } 123 operator ()boost::multi_index::detail::non_const_identity_base124 Type& operator()(const reference_wrapper<Type>& x)const 125 { 126 return x.get(); 127 } 128 }; 129 130 } /* namespace multi_index::detail */ 131 132 template<class Type> 133 struct identity: 134 mpl::if_c< 135 is_const<Type>::value, 136 detail::const_identity_base<Type>,detail::non_const_identity_base<Type> 137 >::type 138 { 139 }; 140 141 } /* namespace multi_index */ 142 143 } /* namespace boost */ 144 145 #endif 146