comparison DEPENDENCIES/generic/include/boost/flyweight/flyweight.hpp @ 16:2665513ce2d3

Add boost headers
author Chris Cannam
date Tue, 05 Aug 2014 11:11:38 +0100
parents
children c530137014c0
comparison
equal deleted inserted replaced
15:663ca0da4350 16:2665513ce2d3
1 /* Flyweight class.
2 *
3 * Copyright 2006-2009 Joaquin M Lopez Munoz.
4 * Distributed under the Boost Software License, Version 1.0.
5 * (See accompanying file LICENSE_1_0.txt or copy at
6 * http://www.boost.org/LICENSE_1_0.txt)
7 *
8 * See http://www.boost.org/libs/flyweight for library home page.
9 */
10
11 #ifndef BOOST_FLYWEIGHT_FLYWEIGHT_HPP
12 #define BOOST_FLYWEIGHT_FLYWEIGHT_HPP
13
14 #if defined(_MSC_VER)&&(_MSC_VER>=1200)
15 #pragma once
16 #endif
17
18 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
19 #include <algorithm>
20 #include <boost/detail/workaround.hpp>
21 #include <boost/flyweight/detail/default_value_policy.hpp>
22 #include <boost/flyweight/detail/flyweight_core.hpp>
23 #include <boost/flyweight/factory_tag.hpp>
24 #include <boost/flyweight/flyweight_fwd.hpp>
25 #include <boost/flyweight/locking_tag.hpp>
26 #include <boost/flyweight/simple_locking_fwd.hpp>
27 #include <boost/flyweight/static_holder_fwd.hpp>
28 #include <boost/flyweight/hashed_factory_fwd.hpp>
29 #include <boost/flyweight/holder_tag.hpp>
30 #include <boost/flyweight/refcounted_fwd.hpp>
31 #include <boost/flyweight/tag.hpp>
32 #include <boost/flyweight/tracking_tag.hpp>
33 #include <boost/mpl/assert.hpp>
34 #include <boost/mpl/if.hpp>
35 #include <boost/mpl/not.hpp>
36 #include <boost/mpl/or.hpp>
37 #include <boost/parameter/binding.hpp>
38 #include <boost/preprocessor/repetition/enum_params.hpp>
39 #include <boost/type_traits/is_same.hpp>
40 #include <boost/utility/swap.hpp>
41
42 #if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1400))
43 #pragma warning(push)
44 #pragma warning(disable:4521) /* multiple copy ctors */
45 #endif
46
47 namespace boost{
48
49 namespace flyweights{
50
51 namespace detail{
52
53 /* Used for the detection of unmatched template args in a
54 * flyweight instantiation.
55 */
56
57 struct unmatched_arg;
58
59 /* Boost.Parameter structures for use in flyweight.
60 * NB: these types are derived from instead of typedef'd to force their
61 * instantiation, which solves http://bugs.sun.com/view_bug.do?bug_id=6782987
62 * as found out by Simon Atanasyan.
63 */
64
65 struct flyweight_signature:
66 parameter::parameters<
67 parameter::optional<
68 parameter::deduced<tag<> >,
69 detail::is_tag<boost::mpl::_>
70 >,
71 parameter::optional<
72 parameter::deduced<tracking<> >,
73 is_tracking<boost::mpl::_>
74 >,
75 parameter::optional<
76 parameter::deduced<factory<> >,
77 is_factory<boost::mpl::_>
78 >,
79 parameter::optional<
80 parameter::deduced<locking<> >,
81 is_locking<boost::mpl::_>
82 >,
83 parameter::optional<
84 parameter::deduced<holder<> >,
85 is_holder<boost::mpl::_>
86 >
87 >
88 {};
89
90 struct flyweight_unmatched_signature:
91 parameter::parameters<
92 parameter::optional<
93 parameter::deduced<
94 detail::unmatched_arg
95 >,
96 mpl::not_<
97 mpl::or_<
98 detail::is_tag<boost::mpl::_>,
99 is_tracking<boost::mpl::_>,
100 is_factory<boost::mpl::_>,
101 is_locking<boost::mpl::_>,
102 is_holder<boost::mpl::_>
103 >
104 >
105 >
106 >
107 {};
108
109 } /* namespace flyweights::detail */
110
111 template<
112 typename T,
113 typename Arg1,typename Arg2,typename Arg3,typename Arg4,typename Arg5
114 >
115 class flyweight
116 {
117 private:
118 typedef typename mpl::if_<
119 detail::is_value<T>,
120 T,
121 detail::default_value_policy<T>
122 >::type value_policy;
123 typedef typename detail::
124 flyweight_signature::bind<
125 Arg1,Arg2,Arg3,Arg4,Arg5
126 >::type args;
127 typedef typename parameter::binding<
128 args,tag<>,mpl::na
129 >::type tag_type;
130 typedef typename parameter::binding<
131 args,tracking<>,refcounted
132 >::type tracking_policy;
133 typedef typename parameter::binding<
134 args,factory<>,hashed_factory<>
135 >::type factory_specifier;
136 typedef typename parameter::binding<
137 args,locking<>,simple_locking
138 >::type locking_policy;
139 typedef typename parameter::binding<
140 args,holder<>,static_holder
141 >::type holder_specifier;
142
143 typedef typename detail::
144 flyweight_unmatched_signature::bind<
145 Arg1,Arg2,Arg3,Arg4,Arg5
146 >::type unmatched_args;
147 typedef typename parameter::binding<
148 unmatched_args,detail::unmatched_arg,
149 detail::unmatched_arg
150 >::type unmatched_arg_detected;
151
152 /* You have passed a type in the specification of a flyweight type that
153 * could not be interpreted as a valid argument.
154 */
155 BOOST_MPL_ASSERT_MSG(
156 (is_same<unmatched_arg_detected,detail::unmatched_arg>::value),
157 INVALID_ARGUMENT_TO_FLYWEIGHT,
158 (flyweight));
159
160 typedef detail::flyweight_core<
161 value_policy,tag_type,tracking_policy,
162 factory_specifier,locking_policy,
163 holder_specifier
164 > core;
165 typedef typename core::handle_type handle_type;
166
167 public:
168 typedef typename value_policy::key_type key_type;
169 typedef typename value_policy::value_type value_type;
170
171 /* static data initialization */
172
173 static bool init(){return core::init();}
174
175 class initializer
176 {
177 public:
178 initializer():b(init()){}
179 private:
180 bool b;
181 };
182
183 /* construct/copy/destroy */
184
185 flyweight():h(core::insert(key_type())){}
186 flyweight(const flyweight& x):h(x.h){}
187 flyweight(flyweight& x):h(x.h){}
188
189 /* template ctors */
190
191 #define BOOST_FLYWEIGHT_PERFECT_FWD_NAME explicit flyweight
192 #define BOOST_FLYWEIGHT_PERFECT_FWD_BODY(n) \
193 :h(core::insert(BOOST_PP_ENUM_PARAMS(n,t))){}
194 #include <boost/flyweight/detail/perfect_fwd.hpp>
195
196 flyweight& operator=(const flyweight& x){h=x.h;return *this;}
197 flyweight& operator=(const value_type& x){return operator=(flyweight(x));}
198
199 /* convertibility to underlying type */
200
201 const key_type& get_key()const{return core::key(h);}
202 const value_type& get()const{return core::value(h);}
203 operator const value_type&()const{return get();}
204
205 /* exact type equality */
206
207 friend bool operator==(const flyweight& x,const flyweight& y)
208 {
209 return &x.get()==&y.get();
210 }
211
212 /* modifiers */
213
214 void swap(flyweight& x){boost::swap(h,x.h);}
215
216 private:
217 handle_type h;
218 };
219
220 #define BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(n) \
221 typename Arg##n##1,typename Arg##n##2,typename Arg##n##3, \
222 typename Arg##n##4,typename Arg##n##5
223 #define BOOST_FLYWEIGHT_TEMPL_ARGS(n) \
224 Arg##n##1,Arg##n##2,Arg##n##3,Arg##n##4,Arg##n##5
225
226 /* Comparison. Unlike exact type comparison defined above, intertype
227 * comparison just forwards to the underlying objects.
228 */
229
230 template<
231 typename T1,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(1),
232 typename T2,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(2)
233 >
234 bool operator==(
235 const flyweight<T1,BOOST_FLYWEIGHT_TEMPL_ARGS(1)>& x,
236 const flyweight<T2,BOOST_FLYWEIGHT_TEMPL_ARGS(2)>& y)
237 {
238 return x.get()==y.get();
239 }
240
241 template<
242 typename T1,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(1),
243 typename T2,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(2)
244 >
245 bool operator<(
246 const flyweight<T1,BOOST_FLYWEIGHT_TEMPL_ARGS(1)>& x,
247 const flyweight<T2,BOOST_FLYWEIGHT_TEMPL_ARGS(2)>& y)
248 {
249 return x.get()<y.get();
250 }
251
252 #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
253 template<
254 typename T1,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(1),
255 typename T2
256 >
257 bool operator==(
258 const flyweight<T1,BOOST_FLYWEIGHT_TEMPL_ARGS(1)>& x,const T2& y)
259 {
260 return x.get()==y;
261 }
262
263 template<
264 typename T1,
265 typename T2,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(2)
266 >
267 bool operator==(
268 const T1& x,const flyweight<T2,BOOST_FLYWEIGHT_TEMPL_ARGS(2)>& y)
269 {
270 return x==y.get();
271 }
272
273 template<
274 typename T1,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(1),
275 typename T2
276 >
277 bool operator<(
278 const flyweight<T1,BOOST_FLYWEIGHT_TEMPL_ARGS(1)>& x,const T2& y)
279 {
280 return x.get()<y;
281 }
282
283 template<
284 typename T1,
285 typename T2,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(2)
286 >
287 bool operator<(
288 const T1& x,const flyweight<T2,BOOST_FLYWEIGHT_TEMPL_ARGS(2)>& y)
289 {
290 return x<y.get();
291 }
292 #endif /* !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) */
293
294 /* rest of comparison operators */
295
296 #define BOOST_FLYWEIGHT_COMPLETE_COMP_OPS(t,a1,a2) \
297 template<t> \
298 inline bool operator!=(const a1& x,const a2& y) \
299 { \
300 return !(x==y); \
301 } \
302 \
303 template<t> \
304 inline bool operator>(const a1& x,const a2& y) \
305 { \
306 return y<x; \
307 } \
308 \
309 template<t> \
310 inline bool operator>=(const a1& x,const a2& y) \
311 { \
312 return !(x<y); \
313 } \
314 \
315 template<t> \
316 inline bool operator<=(const a1& x,const a2& y) \
317 { \
318 return !(y<x); \
319 }
320
321 BOOST_FLYWEIGHT_COMPLETE_COMP_OPS(
322 typename T1 BOOST_PP_COMMA()
323 BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(1) BOOST_PP_COMMA()
324 typename T2 BOOST_PP_COMMA()
325 BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(2),
326 flyweight<
327 T1 BOOST_PP_COMMA() BOOST_FLYWEIGHT_TEMPL_ARGS(1)
328 >,
329 flyweight<
330 T2 BOOST_PP_COMMA() BOOST_FLYWEIGHT_TEMPL_ARGS(2)
331 >)
332
333 #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
334 BOOST_FLYWEIGHT_COMPLETE_COMP_OPS(
335 typename T1 BOOST_PP_COMMA()
336 BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(1) BOOST_PP_COMMA()
337 typename T2,
338 flyweight<
339 T1 BOOST_PP_COMMA() BOOST_FLYWEIGHT_TEMPL_ARGS(1)
340 >,
341 T2)
342
343 BOOST_FLYWEIGHT_COMPLETE_COMP_OPS(
344 typename T1 BOOST_PP_COMMA()
345 typename T2 BOOST_PP_COMMA()
346 BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(2),
347 T1,
348 flyweight<
349 T2 BOOST_PP_COMMA() BOOST_FLYWEIGHT_TEMPL_ARGS(2)
350 >)
351 #endif /* !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) */
352
353 /* specialized algorithms */
354
355 template<typename T,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(_)>
356 void swap(
357 flyweight<T,BOOST_FLYWEIGHT_TEMPL_ARGS(_)>& x,
358 flyweight<T,BOOST_FLYWEIGHT_TEMPL_ARGS(_)>& y)
359 {
360 x.swap(y);
361 }
362
363 template<
364 BOOST_TEMPLATED_STREAM_ARGS(ElemType,Traits)
365 BOOST_TEMPLATED_STREAM_COMMA
366 typename T,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(_)
367 >
368 BOOST_TEMPLATED_STREAM(ostream,ElemType,Traits)& operator<<(
369 BOOST_TEMPLATED_STREAM(ostream,ElemType,Traits)& out,
370 const flyweight<T,BOOST_FLYWEIGHT_TEMPL_ARGS(_)>& x)
371 {
372 return out<<x.get();
373 }
374
375 template<
376 BOOST_TEMPLATED_STREAM_ARGS(ElemType,Traits)
377 BOOST_TEMPLATED_STREAM_COMMA
378 typename T,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(_)
379 >
380 BOOST_TEMPLATED_STREAM(istream,ElemType,Traits)& operator>>(
381 BOOST_TEMPLATED_STREAM(istream,ElemType,Traits)& in,
382 flyweight<T,BOOST_FLYWEIGHT_TEMPL_ARGS(_)>& x)
383 {
384 typedef typename flyweight<
385 T,BOOST_FLYWEIGHT_TEMPL_ARGS(_)
386 >::value_type value_type;
387
388 /* value_type need not be default ctble but must be copy ctble */
389 value_type t(x.get());
390 in>>t;
391 x=t;
392 return in;
393 }
394
395 } /* namespace flyweights */
396
397 } /* namespace boost */
398
399 #undef BOOST_FLYWEIGHT_COMPLETE_COMP_OPS
400 #undef BOOST_FLYWEIGHT_TEMPL_ARGS
401 #undef BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS
402
403 #if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1400))
404 #pragma warning(pop)
405 #endif
406
407 #endif