]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/flyweight/include/boost/flyweight/key_value.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / flyweight / include / boost / flyweight / key_value.hpp
CommitLineData
7c673cae
FG
1/* Copyright 2006-2014 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/flyweight for library home page.
7 */
8
9#ifndef BOOST_FLYWEIGHT_KEY_VALUE_HPP
10#define BOOST_FLYWEIGHT_KEY_VALUE_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/detail/workaround.hpp>
18#include <boost/flyweight/detail/perfect_fwd.hpp>
19#include <boost/flyweight/detail/value_tag.hpp>
20#include <boost/flyweight/key_value_fwd.hpp>
21#include <boost/mpl/assert.hpp>
22#include <boost/type_traits/aligned_storage.hpp>
23#include <boost/type_traits/alignment_of.hpp>
24#include <boost/type_traits/is_same.hpp>
25#include <new>
26
27/* key-value policy: flywewight lookup is based on Key, which also serves
28 * to construct Value only when needed (new factory entry). key_value is
29 * used to avoid the construction of temporary values when such construction
30 * is expensive.
31 * Optionally, KeyFromValue extracts the key from a value, which
32 * is needed in expressions like this:
33 *
34 * typedef flyweight<key_value<Key,Value> > fw_t;
35 * fw_t fw;
36 * Value v;
37 * fw=v; // no key explicitly given
38 *
39 * If no KeyFromValue is provided, this latter expression fails to compile.
40 */
41
42namespace boost{
43
44namespace flyweights{
45
46namespace detail{
47
48template<typename Key,typename Value,typename KeyFromValue>
49struct optimized_key_value:value_marker
50{
51 typedef Key key_type;
52 typedef Value value_type;
53
54 class rep_type
55 {
56 public:
57 /* template ctors */
58
59#define BOOST_FLYWEIGHT_PERFECT_FWD_CTR_BODY(args) \
60 :value_ptr(0) \
61{ \
62 new(spc_ptr())key_type(BOOST_FLYWEIGHT_FORWARD(args)); \
63}
64
65 BOOST_FLYWEIGHT_PERFECT_FWD(
66 explicit rep_type,
67 BOOST_FLYWEIGHT_PERFECT_FWD_CTR_BODY)
68
69#undef BOOST_FLYWEIGHT_PERFECT_FWD_CTR_BODY
70
71 rep_type(const rep_type& x):value_ptr(x.value_ptr)
72 {
73 if(!x.value_ptr)new(key_ptr())key_type(*x.key_ptr());
74 }
75
76 rep_type(const value_type& x):value_ptr(&x){}
77
78#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
79 rep_type(rep_type&& x):value_ptr(x.value_ptr)
80 {
81 if(!x.value_ptr)new(key_ptr())key_type(std::move(*x.key_ptr()));
82 }
83
84 rep_type(value_type&& x):value_ptr(&x){}
85#endif
86
87 ~rep_type()
88 {
89 if(!value_ptr) key_ptr()->~key_type();
90 else if(value_cted())value_ptr->~value_type();
91 }
92
93 operator const key_type&()const
94 {
95 if(value_ptr)return key_from_value(*value_ptr);
96 else return *key_ptr();
97 }
98
99 operator const value_type&()const
100 {
101 /* This is always called after construct_value() or copy_value(),
102 * so we access spc directly rather than through value_ptr to
103 * save us an indirection.
104 */
105
106 return *static_cast<value_type*>(spc_ptr());
107 }
108
109 private:
110 friend struct optimized_key_value;
111
112 void* spc_ptr()const{return static_cast<void*>(&spc);}
113 bool value_cted()const{return value_ptr==spc_ptr();}
114
115 key_type* key_ptr()const
116 {
117 return static_cast<key_type*>(static_cast<void*>(&spc));
118 }
119
120 static const key_type& key_from_value(const value_type& x)
121 {
122 KeyFromValue k;
123 return k(x);
124 }
125
126 void construct_value()const
127 {
128 if(!value_cted()){
129 /* value_ptr must be ==0, oherwise copy_value would have been called */
130
131#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
132 key_type k(std::move(*key_ptr()));
133#else
134 key_type k(*key_ptr());
135#endif
136
137 key_ptr()->~key_type();
138 value_ptr= /* guarantees key won't be re-dted at ~rep_type if the */
139 static_cast<value_type*>(spc_ptr())+1; /* next statement throws */
140 value_ptr=new(spc_ptr())value_type(k);
141 }
142 }
143
144 void copy_value()const
145 {
146 if(!value_cted())value_ptr=new(spc_ptr())value_type(*value_ptr);
147 }
148
149#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
150 void move_value()const
151 {
152 if(!value_cted())value_ptr=
153 new(spc_ptr())value_type(std::move(const_cast<value_type&>(*value_ptr)));
154 }
155#endif
156
157 mutable typename boost::aligned_storage<
158 (sizeof(key_type)>sizeof(value_type))?
159 sizeof(key_type):sizeof(value_type),
160 (boost::alignment_of<key_type>::value >
161 boost::alignment_of<value_type>::value)?
162 boost::alignment_of<key_type>::value:
163 boost::alignment_of<value_type>::value
164 >::type spc;
165 mutable const value_type* value_ptr;
166 };
167
168 static void construct_value(const rep_type& r)
169 {
170 r.construct_value();
171 }
172
173 static void copy_value(const rep_type& r)
174 {
175 r.copy_value();
176 }
177
178#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
179 static void move_value(const rep_type& r)
180 {
181 r.move_value();
182 }
183#endif
184};
185
186template<typename Key,typename Value>
187struct regular_key_value:value_marker
188{
189 typedef Key key_type;
190 typedef Value value_type;
191
192 class rep_type
193 {
194 public:
195 /* template ctors */
196
197#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)&&\
198 !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)&&\
199 BOOST_WORKAROUND(__GNUC__,<=4)&&(__GNUC__<4||__GNUC_MINOR__<=4)
200
201/* GCC 4.4.2 (and probably prior) bug: the default ctor generated by the
202 * variadic temmplate ctor below fails to value-initialize key.
203 */
204
205 rep_type():key(),value_ptr(0){}
206#endif
207
208#define BOOST_FLYWEIGHT_PERFECT_FWD_CTR_BODY(args) \
209 :key(BOOST_FLYWEIGHT_FORWARD(args)),value_ptr(0){}
210
211 BOOST_FLYWEIGHT_PERFECT_FWD(
212 explicit rep_type,
213 BOOST_FLYWEIGHT_PERFECT_FWD_CTR_BODY)
214
215#undef BOOST_FLYWEIGHT_PERFECT_FWD_CTR_BODY
216
217 rep_type(const rep_type& x):key(x.key),value_ptr(0){}
218 rep_type(const value_type& x):key(no_key_from_value_failure()){}
219
220#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
221 rep_type(rep_type&& x):key(std::move(x.key)),value_ptr(0){}
222 rep_type(value_type&& x):key(no_key_from_value_failure()){}
223#endif
224
225 ~rep_type()
226 {
227 if(value_ptr)value_ptr->~value_type();
228 }
229
230 operator const key_type&()const{return key;}
231
232 operator const value_type&()const
233 {
234 /* This is always called after construct_value(),so we access spc
235 * directly rather than through value_ptr to save us an indirection.
236 */
237
238 return *static_cast<value_type*>(spc_ptr());
239 }
240
241 private:
242 friend struct regular_key_value;
243
244 void* spc_ptr()const{return static_cast<void*>(&spc);}
245
246 struct no_key_from_value_failure
247 {
248 BOOST_MPL_ASSERT_MSG(
249 false,
250 NO_KEY_FROM_VALUE_CONVERSION_PROVIDED,
251 (key_type,value_type));
252
253 operator const key_type&()const;
254 };
255
256 void construct_value()const
257 {
258 if(!value_ptr)value_ptr=new(spc_ptr())value_type(key);
259 }
260
261 key_type key;
262 mutable typename boost::aligned_storage<
263 sizeof(value_type),
264 boost::alignment_of<value_type>::value
265 >::type spc;
266 mutable const value_type* value_ptr;
267 };
268
269 static void construct_value(const rep_type& r)
270 {
271 r.construct_value();
272 }
273
274 /* copy_value() and move_value() can't really ever be called, provided to avoid
275 * compile errors (it is the no_key_from_value_failure compile error we want to
276 * appear in these cases).
277 */
278
279 static void copy_value(const rep_type&){}
280
281#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
282 static void move_value(const rep_type&){}
283#endif
284};
285
286} /* namespace flyweights::detail */
287
288template<typename Key,typename Value,typename KeyFromValue>
289struct key_value:
290 mpl::if_<
291 is_same<KeyFromValue,no_key_from_value>,
292 detail::regular_key_value<Key,Value>,
293 detail::optimized_key_value<Key,Value,KeyFromValue>
294 >::type
295{};
296
297} /* namespace flyweights */
298
299} /* namespace boost */
300
301#endif