b3c95680357cac49e671e59beff438eca892ca7a
[senf.git] / boost / multi_index / identity.hpp
1 /* Copyright 2003-2006 Joaquín M López Muñoz.
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)&&(_MSC_VER>=1200)
13 #pragma once
14 #endif
15
16 #include <boost/config.hpp>
17 #include <boost/mpl/if.hpp>
18 #include <boost/multi_index/identity_fwd.hpp>
19 #include <boost/type_traits/is_const.hpp>
20 #include <boost/type_traits/remove_const.hpp>
21 #include <boost/utility/enable_if.hpp>
22
23 #if !defined(BOOST_NO_SFINAE)
24 #include <boost/type_traits/is_convertible.hpp>
25 #endif
26
27 namespace boost{
28
29 template<class Type> class reference_wrapper; /* fwd decl. */
30
31 namespace multi_index{
32
33 namespace detail{
34
35 /* identity is a do-nothing key extractor that returns the [const] Type&
36  * object passed.
37  * Additionally, identity is overloaded to support referece_wrappers
38  * of Type and "chained pointers" to Type's. By chained pointer to Type we
39  * mean a  type  P such that, given a p of type P
40  *   *...n...*x is convertible to Type&, for some n>=1.
41  * Examples of chained pointers are raw and smart pointers, iterators and
42  * arbitrary combinations of these (vg. Type** or auto_ptr<Type*>.)
43  */
44
45 /* NB. Some overloads of operator() have an extra dummy parameter int=0.
46  * This disambiguator serves several purposes:
47  *  - Without it, MSVC++ 6.0 incorrectly regards some overloads as
48  *    specializations of a previous member function template.
49  *  - MSVC++ 6.0/7.0 seem to incorrectly treat some different memfuns
50  *    as if they have the same signature.
51  *  - If remove_const is broken due to lack of PTS, int=0 avoids the
52  *    declaration of memfuns with identical signature.
53  */
54
55 template<typename Type>
56 struct const_identity_base
57 {
58   typedef Type result_type;
59
60   template<typename ChainedPtr>
61
62 #if !defined(BOOST_NO_SFINAE)
63   typename disable_if<is_convertible<const ChainedPtr&,Type&>,Type&>::type
64 #else
65   Type&
66 #endif 
67   
68   operator()(const ChainedPtr& x)const
69   {
70     return operator()(*x);
71   }
72
73   Type& operator()(Type& x)const
74   {
75     return x;
76   }
77
78   Type& operator()(const reference_wrapper<Type>& x)const
79   { 
80     return x.get();
81   }
82
83   Type& operator()(
84     const reference_wrapper<typename remove_const<Type>::type>& x,int=0)const
85   { 
86     return x.get();
87   }
88 };
89
90 template<typename Type>
91 struct non_const_identity_base
92 {
93   typedef Type result_type;
94
95   /* templatized for pointer-like types */
96   
97   template<typename ChainedPtr>
98
99 #if !defined(BOOST_NO_SFINAE)
100   typename disable_if<
101     is_convertible<const ChainedPtr&,const Type&>,Type&>::type
102 #else
103   Type&
104 #endif 
105     
106   operator()(const ChainedPtr& x)const
107   {
108     return operator()(*x);
109   }
110
111   const Type& operator()(const Type& x,int=0)const
112   {
113     return x;
114   }
115
116   Type& operator()(Type& x)const
117   {
118     return x;
119   }
120
121   const Type& operator()(const reference_wrapper<const Type>& x,int=0)const
122   { 
123     return x.get();
124   }
125
126   Type& operator()(const reference_wrapper<Type>& x)const
127   { 
128     return x.get();
129   }
130 };
131
132 } /* namespace multi_index::detail */
133
134 template<class Type>
135 struct identity:
136   mpl::if_c<
137     is_const<Type>::value,
138     detail::const_identity_base<Type>,detail::non_const_identity_base<Type>
139   >::type
140 {
141 };
142
143 } /* namespace multi_index */
144
145 } /* namespace boost */
146
147 #endif