Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/boost/multi_index/member.hpp @ 44

Last change on this file since 44 was 29, checked in by landauf, 16 years ago

updated boost from 1_33_1 to 1_34_1

File size: 6.7 KB
Line 
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
26namespace boost{
27
28template<class T> class reference_wrapper; /* fwd decl. */
29
30namespace multi_index{
31
32namespace 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
54template<class Class,typename Type,Type Class::*PtrToMember>
55struct 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
89template<class Class,typename Type,Type Class::*PtrToMember>
90struct 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
131template<class Class,typename Type,Type Class::*PtrToMember>
132struct 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
141namespace 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
157template<class Class,typename Type,std::size_t OffsetOfMember>
158struct 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
195template<class Class,typename Type,std::size_t OffsetOfMember>
196struct 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
242template<class Class,typename Type,std::size_t OffsetOfMember>
243struct 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
Note: See TracBrowser for help on using the repository browser.