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_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/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
27namespace boost{
28
29template<class Type> class reference_wrapper; /* fwd decl. */
30
31namespace multi_index{
32
33namespace 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
45template<typename Type>
46struct const_identity_base
47{
48 typedef Type result_type;
49
50 template<typename ChainedPtr>
51
52#if !defined(BOOST_NO_SFINAE)
53 typename disable_if<is_convertible<const ChainedPtr&,Type&>,Type&>::type
54#else
55 Type&
56#endif
57
58 operator()(const ChainedPtr& x)const
59 {
60 return operator()(*x);
61 }
62
63 Type& operator()(Type& x)const
64 {
65 return x;
66 }
67
68 Type& operator()(const reference_wrapper<Type>& x)const
69 {
70 return x.get();
71 }
72
73 Type& operator()(
74 const reference_wrapper<typename remove_const<Type>::type>& x)const
75 {
76 return x.get();
77 }
78};
79
80template<typename Type>
81struct non_const_identity_base
82{
83 typedef Type result_type;
84
85 /* templatized for pointer-like types */
86
87 template<typename ChainedPtr>
88
89#if !defined(BOOST_NO_SFINAE)
90 typename disable_if<
91 is_convertible<const ChainedPtr&,const Type&>,Type&>::type
92#else
93 Type&
94#endif
95
96 operator()(const ChainedPtr& x)const
97 {
98 return operator()(*x);
99 }
100
101 const Type& operator()(const Type& x)const
102 {
103 return x;
104 }
105
106 Type& operator()(Type& x)const
107 {
108 return x;
109 }
110
111 const Type& operator()(const reference_wrapper<const Type>& x)const
112 {
113 return x.get();
114 }
115
116 Type& operator()(const reference_wrapper<Type>& x)const
117 {
118 return x.get();
119 }
120};
121
122} /* namespace multi_index::detail */
123
124template<class Type>
125struct identity:
126 mpl::if_c<
127 is_const<Type>::value,
128 detail::const_identity_base<Type>,detail::non_const_identity_base<Type>
129 >::type
130{
131};
132
133} /* namespace multi_index */
134
135} /* namespace boost */
136
137#endif
138