Coverage Report

Created: 2025-11-16 06:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/boost/boost/multi_index/member.hpp
Line
Count
Source
1
/* Copyright 2003-2022 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_MEMBER_HPP
10
#define BOOST_MULTI_INDEX_MEMBER_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/core/enable_if.hpp>
18
#include <boost/mpl/if.hpp>
19
#include <boost/type_traits/is_const.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 unique_ptr<T*>.)
42
 */
43
44
template<class Class,typename Type,Type Class::*PtrToMember>
45
struct const_member_base
46
{
47
  typedef Type result_type;
48
49
  template<typename ChainedPtr>
50
51
#if !defined(BOOST_NO_SFINAE)
52
  typename disable_if<
53
    is_convertible<const ChainedPtr&,const Class&>,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()(const Class& x)const
64
252M
  {
65
252M
    return x.*PtrToMember;
66
252M
  }
67
68
  Type& operator()(const reference_wrapper<const Class>& x)const
69
  {
70
    return operator()(x.get());
71
  }
72
73
  Type& operator()(const reference_wrapper<Class>& x)const
74
  { 
75
    return operator()(x.get());
76
  }
77
};
78
79
template<class Class,typename Type,Type Class::*PtrToMember>
80
struct non_const_member_base
81
{
82
  typedef Type result_type;
83
84
  template<typename ChainedPtr>
85
86
#if !defined(BOOST_NO_SFINAE)
87
  typename disable_if<
88
    is_convertible<const ChainedPtr&,const Class&>,Type&>::type
89
#else
90
  Type&
91
#endif
92
93
  operator()(const ChainedPtr& x)const
94
  {
95
    return operator()(*x);
96
  }
97
98
  const Type& operator()(const Class& x)const
99
  {
100
    return x.*PtrToMember;
101
  }
102
103
  Type& operator()(Class& x)const
104
  { 
105
    return x.*PtrToMember;
106
  }
107
108
  const Type& operator()(const reference_wrapper<const Class>& x)const
109
  {
110
    return operator()(x.get());
111
  }
112
113
  Type& operator()(const reference_wrapper<Class>& x)const
114
  { 
115
    return operator()(x.get());
116
  }
117
};
118
119
} /* namespace multi_index::detail */
120
121
template<class Class,typename Type,Type Class::*PtrToMember>
122
struct member:
123
  mpl::if_c<
124
    is_const<Type>::value,
125
    detail::const_member_base<Class,Type,PtrToMember>,
126
    detail::non_const_member_base<Class,Type,PtrToMember>
127
  >::type
128
{
129
};
130
131
namespace detail{
132
133
/* MSVC++ 6.0 does not support properly pointers to members as
134
 * non-type template arguments, as reported in
135
 *   http://support.microsoft.com/default.aspx?scid=kb;EN-US;249045
136
 * A similar problem (though not identical) is shown by MSVC++ 7.0.
137
 * We provide an alternative to member<> accepting offsets instead
138
 * of pointers to members. This happens to work even for non-POD
139
 * types (although the standard forbids use of offsetof on these),
140
 * so it serves as a workaround in this compiler for all practical
141
 * purposes.
142
 * Surprisingly enough, other compilers, like Intel C++ 7.0/7.1 and
143
 * Visual Age 6.0, have similar bugs. This replacement of member<>
144
 * can be used for them too.
145
 *
146
 * Support for such old compilers is dropped and
147
 * [non_]const_member_offset_base is deprecated.
148
 */
149
150
template<class Class,typename Type,std::size_t OffsetOfMember>
151
struct const_member_offset_base
152
{
153
  typedef Type result_type;
154
155
  template<typename ChainedPtr>
156
157
#if !defined(BOOST_NO_SFINAE)
158
  typename disable_if<
159
    is_convertible<const ChainedPtr&,const Class&>,Type&>::type
160
#else
161
  Type&
162
#endif 
163
    
164
  operator()(const ChainedPtr& x)const
165
  {
166
    return operator()(*x);
167
  }
168
169
  Type& operator()(const Class& x)const
170
  {
171
    return *static_cast<const Type*>(
172
      static_cast<const void*>(
173
        static_cast<const char*>(
174
          static_cast<const void *>(&x))+OffsetOfMember));
175
  }
176
177
  Type& operator()(const reference_wrapper<const Class>& x)const
178
  {
179
    return operator()(x.get());
180
  }
181
182
  Type& operator()(const reference_wrapper<Class>& x)const
183
  {
184
    return operator()(x.get());
185
  }
186
};
187
188
template<class Class,typename Type,std::size_t OffsetOfMember>
189
struct non_const_member_offset_base
190
{
191
  typedef Type result_type;
192
193
  template<typename ChainedPtr>
194
195
#if !defined(BOOST_NO_SFINAE)
196
  typename disable_if<
197
    is_convertible<const ChainedPtr&,const Class&>,Type&>::type
198
#else
199
  Type&
200
#endif 
201
  
202
  operator()(const ChainedPtr& x)const
203
  {
204
    return operator()(*x);
205
  }
206
207
  const Type& operator()(const Class& x)const
208
  {
209
    return *static_cast<const Type*>(
210
      static_cast<const void*>(
211
        static_cast<const char*>(
212
          static_cast<const void *>(&x))+OffsetOfMember));
213
  }
214
215
  Type& operator()(Class& x)const
216
  { 
217
    return *static_cast<Type*>(
218
      static_cast<void*>(
219
        static_cast<char*>(static_cast<void *>(&x))+OffsetOfMember));
220
  }
221
222
  const Type& operator()(const reference_wrapper<const Class>& x)const
223
  {
224
    return operator()(x.get());
225
  }
226
227
  Type& operator()(const reference_wrapper<Class>& x)const
228
  {
229
    return operator()(x.get());
230
  }
231
};
232
233
} /* namespace multi_index::detail */
234
235
template<class Class,typename Type,std::size_t OffsetOfMember>
236
struct member_offset:
237
  mpl::if_c<
238
    is_const<Type>::value,
239
    detail::const_member_offset_base<Class,Type,OffsetOfMember>,
240
    detail::non_const_member_offset_base<Class,Type,OffsetOfMember>
241
  >::type
242
{
243
};
244
245
/* BOOST_MULTI_INDEX_MEMBER resolves to member in the normal cases,
246
 * and to member_offset as a workaround in those defective compilers for
247
 * which BOOST_NO_POINTER_TO_MEMBER_TEMPLATE_PARAMETERS is defined.
248
 */
249
250
#if defined(BOOST_NO_POINTER_TO_MEMBER_TEMPLATE_PARAMETERS)
251
#define BOOST_MULTI_INDEX_MEMBER(Class,Type,MemberName) \
252
::boost::multi_index::member_offset< Class,Type,offsetof(Class,MemberName) >
253
#else
254
#define BOOST_MULTI_INDEX_MEMBER(Class,Type,MemberName) \
255
::boost::multi_index::member< Class,Type,&Class::MemberName >
256
#endif
257
258
} /* namespace multi_index */
259
260
} /* namespace boost */
261
262
#endif