Add Boost.Test karmic valgrind suppressions
[senf.git] / boost / multi_index / member.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_MEMBER_HPP
10 #define BOOST_MULTI_INDEX_MEMBER_HPP
11
12 #if defined(_MSC_VER)&&(_MSC_VER>=1200)
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/utility/enable_if.hpp>
20 #include <cstddef>
21
22 #if !defined(BOOST_NO_SFINAE)
23 #include <boost/type_traits/is_convertible.hpp>
24 #endif
25
26 namespace boost{
27
28 template<class T> class reference_wrapper; /* fwd decl. */
29
30 namespace multi_index{
31
32 namespace detail{
33
34 /* member is a read/write key extractor for accessing a given
35  * member of a class.
36  * Additionally, member is overloaded to support referece_wrappers
37  * of T and "chained pointers" to T's. By chained pointer to T we mean
38  * a type P  such that, given a p of Type P
39  *   *...n...*x is convertible to T&, for some n>=1.
40  * Examples of chained pointers are raw and smart pointers, iterators and
41  * arbitrary combinations of these (vg. T** or auto_ptr<T*>.)
42  */
43
44 /* NB. Some overloads of operator() have an extra dummy parameter int=0.
45  * This disambiguator serves several purposes:
46  *  - Without it, MSVC++ 6.0 incorrectly regards some overloads as
47  *    specializations of a previous member function template.
48  *  - MSVC++ 6.0/7.0 seem to incorrectly treat some different memfuns
49  *    as if they have the same signature.
50  *  - If remove_const is broken due to lack of PTS, int=0 avoids the
51  *    declaration of memfuns with identical signature.
52  */
53
54 template<class Class,typename Type,Type Class::*PtrToMember>
55 struct const_member_base
56 {
57   typedef Type result_type;
58
59   template<typename ChainedPtr>
60
61 #if !defined(BOOST_NO_SFINAE)
62   typename disable_if<
63     is_convertible<const ChainedPtr&,const Class&>,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()(const Class& x)const
74   {
75     return x.*PtrToMember;
76   }
77
78   Type& operator()(const reference_wrapper<const Class>& x)const
79   {
80     return operator()(x.get());
81   }
82
83   Type& operator()(const reference_wrapper<Class>& x,int=0)const
84   { 
85     return operator()(x.get());
86   }
87 };
88
89 template<class Class,typename Type,Type Class::*PtrToMember>
90 struct non_const_member_base
91 {
92   typedef Type result_type;
93
94   template<typename ChainedPtr>
95
96 #if !defined(BOOST_NO_SFINAE)
97   typename disable_if<
98     is_convertible<const ChainedPtr&,const Class&>,Type&>::type
99 #else
100   Type&
101 #endif
102
103   operator()(const ChainedPtr& x)const
104   {
105     return operator()(*x);
106   }
107
108   const Type& operator()(const Class& x,int=0)const
109   {
110     return x.*PtrToMember;
111   }
112
113   Type& operator()(Class& x)const
114   { 
115     return x.*PtrToMember;
116   }
117
118   const Type& operator()(const reference_wrapper<const Class>& x,int=0)const
119   {
120     return operator()(x.get());
121   }
122
123   Type& operator()(const reference_wrapper<Class>& x)const
124   { 
125     return operator()(x.get());
126   }
127 };
128
129 } /* namespace multi_index::detail */
130
131 template<class Class,typename Type,Type Class::*PtrToMember>
132 struct member:
133   mpl::if_c<
134     is_const<Type>::value,
135     detail::const_member_base<Class,Type,PtrToMember>,
136     detail::non_const_member_base<Class,Type,PtrToMember>
137   >::type
138 {
139 };
140
141 namespace detail{
142
143 /* MSVC++ 6.0 does not support properly pointers to members as
144  * non-type template arguments, as reported in
145  *   http://support.microsoft.com/default.aspx?scid=kb;EN-US;249045
146  * A similar problem (though not identical) is shown by MSVC++ 7.0.
147  * We provide an alternative to member<> accepting offsets instead
148  * of pointers to members. This happens to work even for non-POD
149  * types (although the standard forbids use of offsetof on these),
150  * so it serves as a workaround in this compiler for all practical
151  * purposes.
152  * Surprisingly enough, other compilers, like Intel C++ 7.0/7.1 and
153  * Visual Age 6.0, have similar bugs. This replacement of member<>
154  * can be used for them too.
155  */
156
157 template<class Class,typename Type,std::size_t OffsetOfMember>
158 struct const_member_offset_base
159 {
160   typedef Type result_type;
161
162   template<typename ChainedPtr>
163
164 #if !defined(BOOST_NO_SFINAE)
165   typename disable_if<
166     is_convertible<const ChainedPtr&,const Class&>,Type&>::type
167 #else
168   Type&
169 #endif 
170     
171   operator()(const ChainedPtr& x)const
172   {
173     return operator()(*x);
174   }
175
176   Type& operator()(const Class& x)const
177   {
178     return *static_cast<const Type*>(
179       static_cast<const void*>(
180         static_cast<const char*>(
181           static_cast<const void *>(&x))+OffsetOfMember));
182   }
183
184   Type& operator()(const reference_wrapper<const Class>& x)const
185   {
186     return operator()(x.get());
187   }
188
189   Type& operator()(const reference_wrapper<Class>& x,int=0)const
190   {
191     return operator()(x.get());
192   }
193 };
194
195 template<class Class,typename Type,std::size_t OffsetOfMember>
196 struct non_const_member_offset_base
197 {
198   typedef Type result_type;
199
200   template<typename ChainedPtr>
201
202 #if !defined(BOOST_NO_SFINAE)
203   typename disable_if<
204     is_convertible<const ChainedPtr&,const Class&>,Type&>::type
205 #else
206   Type&
207 #endif 
208   
209   operator()(const ChainedPtr& x)const
210   {
211     return operator()(*x);
212   }
213
214   const Type& operator()(const Class& x,int=0)const
215   {
216     return *static_cast<const Type*>(
217       static_cast<const void*>(
218         static_cast<const char*>(
219           static_cast<const void *>(&x))+OffsetOfMember));
220   }
221
222   Type& operator()(Class& x)const
223   { 
224     return *static_cast<Type*>(
225       static_cast<void*>(
226         static_cast<char*>(static_cast<void *>(&x))+OffsetOfMember));
227   }
228
229   const Type& operator()(const reference_wrapper<const Class>& x,int=0)const
230   {
231     return operator()(x.get());
232   }
233
234   Type& operator()(const reference_wrapper<Class>& x)const
235   {
236     return operator()(x.get());
237   }
238 };
239
240 } /* namespace multi_index::detail */
241
242 template<class Class,typename Type,std::size_t OffsetOfMember>
243 struct member_offset:
244   mpl::if_c<
245     is_const<Type>::value,
246     detail::const_member_offset_base<Class,Type,OffsetOfMember>,
247     detail::non_const_member_offset_base<Class,Type,OffsetOfMember>
248   >::type
249 {
250 };
251
252 /* BOOST_MULTI_INDEX_MEMBER resolves to member in the normal cases,
253  * and to member_offset as a workaround in those defective compilers for
254  * which BOOST_NO_POINTER_TO_MEMBER_TEMPLATE_PARAMETERS is defined.
255  */
256
257 #if defined(BOOST_NO_POINTER_TO_MEMBER_TEMPLATE_PARAMETERS)
258 #define BOOST_MULTI_INDEX_MEMBER(Class,Type,MemberName) \
259 ::boost::multi_index::member_offset< Class,Type,offsetof(Class,MemberName) >
260 #else
261 #define BOOST_MULTI_INDEX_MEMBER(Class,Type,MemberName) \
262 ::boost::multi_index::member< Class,Type,&Class::MemberName >
263 #endif
264
265 } /* namespace multi_index */
266
267 } /* namespace boost */
268
269 #endif