9333f5891eb21b26a555526b56ee57d36beaa9c0
[platform/upstream/boost.git] / boost / multi_index / global_fun.hpp
1 /* Copyright 2003-2013 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_GLOBAL_FUN_HPP
10 #define BOOST_MULTI_INDEX_GLOBAL_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/is_const.hpp>
19 #include <boost/type_traits/is_reference.hpp>
20 #include <boost/type_traits/remove_const.hpp>
21 #include <boost/type_traits/remove_reference.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 T> class reference_wrapper; /* fwd decl. */
31
32 namespace multi_index{
33
34 namespace detail{
35
36 /* global_fun is a read-only key extractor from Value based on a given global
37  * (or static member) function with signature:
38  *
39  *   Type f([const] Value [&]);
40  *
41  * Additionally, global_fun  and const_global_fun are overloaded to support
42  * referece_wrappers of Value and "chained pointers" to Value's. By chained
43  * pointer to T we  mean a type P such that, given a p of Type P
44  *   *...n...*x is convertible to T&, for some n>=1.
45  * Examples of chained pointers are raw and smart pointers, iterators and
46  * arbitrary combinations of these (vg. T** or auto_ptr<T*>.)
47  */
48
49 template<class Value,typename Type,Type (*PtrToFunction)(Value)>
50 struct const_ref_global_fun_base
51 {
52   typedef typename remove_reference<Type>::type result_type;
53
54   template<typename ChainedPtr>
55
56 #if !defined(BOOST_NO_SFINAE)
57   typename disable_if<
58     is_convertible<const ChainedPtr&,Value>,Type>::type
59 #else
60   Type
61 #endif
62
63   operator()(const ChainedPtr& x)const
64   {
65     return operator()(*x);
66   }
67
68   Type operator()(Value x)const
69   {
70     return PtrToFunction(x);
71   }
72
73   Type operator()(
74     const reference_wrapper<
75       typename remove_reference<Value>::type>& x)const
76   { 
77     return operator()(x.get());
78   }
79
80   Type operator()(
81     const reference_wrapper<
82       typename remove_const<
83         typename remove_reference<Value>::type>::type>& x)const
84   { 
85     return operator()(x.get());
86   }
87 };
88
89 template<class Value,typename Type,Type (*PtrToFunction)(Value)>
90 struct non_const_ref_global_fun_base
91 {
92   typedef typename remove_reference<Type>::type result_type;
93
94   template<typename ChainedPtr>
95
96 #if !defined(BOOST_NO_SFINAE)
97   typename disable_if<
98     is_convertible<ChainedPtr&,Value>,Type>::type
99 #else
100   Type
101 #endif
102
103   operator()(const ChainedPtr& x)const
104   {
105     return operator()(*x);
106   }
107
108   Type operator()(Value x)const
109   {
110     return PtrToFunction(x);
111   }
112
113   Type operator()(
114     const reference_wrapper<
115       typename remove_reference<Value>::type>& x)const
116   { 
117     return operator()(x.get());
118   }
119 };
120
121 template<class Value,typename Type,Type (*PtrToFunction)(Value)>
122 struct non_ref_global_fun_base
123 {
124   typedef typename remove_reference<Type>::type result_type;
125
126   template<typename ChainedPtr>
127
128 #if !defined(BOOST_NO_SFINAE)
129   typename disable_if<
130     is_convertible<const ChainedPtr&,const Value&>,Type>::type
131 #else
132   Type
133 #endif
134
135   operator()(const ChainedPtr& x)const
136   {
137     return operator()(*x);
138   }
139
140   Type operator()(const Value& x)const
141   {
142     return PtrToFunction(x);
143   }
144
145   Type operator()(const reference_wrapper<const Value>& x)const
146   { 
147     return operator()(x.get());
148   }
149
150   Type operator()(
151     const reference_wrapper<typename remove_const<Value>::type>& x)const
152   { 
153     return operator()(x.get());
154   }
155 };
156
157 } /* namespace multi_index::detail */
158
159 template<class Value,typename Type,Type (*PtrToFunction)(Value)>
160 struct global_fun:
161   mpl::if_c<
162     is_reference<Value>::value,
163     typename mpl::if_c<
164       is_const<typename remove_reference<Value>::type>::value,
165       detail::const_ref_global_fun_base<Value,Type,PtrToFunction>,
166       detail::non_const_ref_global_fun_base<Value,Type,PtrToFunction>
167     >::type,
168     detail::non_ref_global_fun_base<Value,Type,PtrToFunction>
169   >::type
170 {
171 };
172
173 } /* namespace multi_index */
174
175 } /* namespace boost */
176
177 #endif