File indexing completed on 2025-12-16 09:45:31
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_FLYWEIGHT_FLYWEIGHT_HPP
0012 #define BOOST_FLYWEIGHT_FLYWEIGHT_HPP
0013
0014 #if defined(_MSC_VER)
0015 #pragma once
0016 #endif
0017
0018 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
0019 #include <algorithm>
0020 #include <boost/config/workaround.hpp>
0021 #include <boost/core/addressof.hpp>
0022 #include <boost/core/invoke_swap.hpp>
0023 #include <boost/flyweight/detail/default_value_policy.hpp>
0024 #include <boost/flyweight/detail/flyweight_core.hpp>
0025 #include <boost/flyweight/detail/perfect_fwd.hpp>
0026 #include <boost/flyweight/factory_tag.hpp>
0027 #include <boost/flyweight/flyweight_fwd.hpp>
0028 #include <boost/flyweight/locking_tag.hpp>
0029 #include <boost/flyweight/simple_locking_fwd.hpp>
0030 #include <boost/flyweight/static_holder_fwd.hpp>
0031 #include <boost/flyweight/hashed_factory_fwd.hpp>
0032 #include <boost/flyweight/holder_tag.hpp>
0033 #include <boost/flyweight/refcounted_fwd.hpp>
0034 #include <boost/flyweight/tag.hpp>
0035 #include <boost/flyweight/tracking_tag.hpp>
0036 #include <boost/mpl/assert.hpp>
0037 #include <boost/mpl/if.hpp>
0038 #include <boost/mpl/not.hpp>
0039 #include <boost/mpl/or.hpp>
0040 #include <boost/parameter/binding.hpp>
0041 #include <boost/type_traits/is_same.hpp>
0042
0043 #if !defined(BOOST_NO_SFINAE)&&!defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
0044 #include <boost/core/enable_if.hpp>
0045 #include <boost/type_traits/is_convertible.hpp>
0046 #include <initializer_list>
0047 #endif
0048
0049 #if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1400))
0050 #pragma warning(push)
0051 #pragma warning(disable:4520)
0052 #pragma warning(disable:4521)
0053 #endif
0054
0055 namespace boost{
0056
0057 namespace flyweights{
0058
0059 namespace detail{
0060
0061
0062
0063
0064
0065 struct unmatched_arg;
0066
0067
0068
0069
0070
0071
0072
0073 struct flyweight_signature:
0074 parameter::parameters<
0075 parameter::optional<
0076 parameter::deduced<tag<> >,
0077 detail::is_tag<boost::mpl::_>
0078 >,
0079 parameter::optional<
0080 parameter::deduced<tracking<> >,
0081 is_tracking<boost::mpl::_>
0082 >,
0083 parameter::optional<
0084 parameter::deduced<factory<> >,
0085 is_factory<boost::mpl::_>
0086 >,
0087 parameter::optional<
0088 parameter::deduced<locking<> >,
0089 is_locking<boost::mpl::_>
0090 >,
0091 parameter::optional<
0092 parameter::deduced<holder<> >,
0093 is_holder<boost::mpl::_>
0094 >
0095 >
0096 {};
0097
0098 struct flyweight_unmatched_signature:
0099 parameter::parameters<
0100 parameter::optional<
0101 parameter::deduced<
0102 detail::unmatched_arg
0103 >,
0104 mpl::not_<
0105 mpl::or_<
0106 detail::is_tag<boost::mpl::_>,
0107 is_tracking<boost::mpl::_>,
0108 is_factory<boost::mpl::_>,
0109 is_locking<boost::mpl::_>,
0110 is_holder<boost::mpl::_>
0111 >
0112 >
0113 >
0114 >
0115 {};
0116
0117 }
0118
0119 template<
0120 typename T,
0121 typename Arg1,typename Arg2,typename Arg3,typename Arg4,typename Arg5
0122 >
0123 class flyweight
0124 {
0125 private:
0126 typedef typename mpl::if_<
0127 detail::is_value<T>,
0128 T,
0129 detail::default_value_policy<T>
0130 >::type value_policy;
0131 typedef typename detail::
0132 flyweight_signature::bind<
0133 Arg1,Arg2,Arg3,Arg4,Arg5
0134 >::type args;
0135 typedef typename parameter::binding<
0136 args,tag<>,mpl::na
0137 >::type tag_type;
0138 typedef typename parameter::binding<
0139 args,tracking<>,refcounted
0140 >::type tracking_policy;
0141 typedef typename parameter::binding<
0142 args,factory<>,hashed_factory<>
0143 >::type factory_specifier;
0144 typedef typename parameter::binding<
0145 args,locking<>,simple_locking
0146 >::type locking_policy;
0147 typedef typename parameter::binding<
0148 args,holder<>,static_holder
0149 >::type holder_specifier;
0150
0151 typedef typename detail::
0152 flyweight_unmatched_signature::bind<
0153 Arg1,Arg2,Arg3,Arg4,Arg5
0154 >::type unmatched_args;
0155 typedef typename parameter::binding<
0156 unmatched_args,detail::unmatched_arg,
0157 detail::unmatched_arg
0158 >::type unmatched_arg_detected;
0159
0160
0161
0162
0163 BOOST_MPL_ASSERT_MSG(
0164 (is_same<unmatched_arg_detected,detail::unmatched_arg>::value),
0165 INVALID_ARGUMENT_TO_FLYWEIGHT,
0166 (flyweight));
0167
0168 typedef detail::flyweight_core<
0169 value_policy,tag_type,tracking_policy,
0170 factory_specifier,locking_policy,
0171 holder_specifier
0172 > core;
0173 typedef typename core::handle_type handle_type;
0174
0175 public:
0176 typedef typename value_policy::key_type key_type;
0177 typedef typename value_policy::value_type value_type;
0178
0179
0180
0181 static bool init(){return core::init();}
0182
0183 class initializer
0184 {
0185 public:
0186 initializer():b(init()){}
0187 private:
0188 bool b;
0189 };
0190
0191
0192
0193 flyweight():h(core::insert()){}
0194
0195 #define BOOST_FLYWEIGHT_PERFECT_FWD_CTR_BODY(args) \
0196 :h(core::insert(BOOST_FLYWEIGHT_FORWARD(args))){}
0197
0198 BOOST_FLYWEIGHT_PERFECT_FWD_WITH_ARGS(
0199 explicit flyweight,
0200 BOOST_FLYWEIGHT_PERFECT_FWD_CTR_BODY)
0201
0202 #undef BOOST_FLYWEIGHT_PERFECT_FWD_CTR_BODY
0203
0204 #if !defined(BOOST_NO_SFINAE)&&!defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
0205 template<typename V>
0206 flyweight(
0207 std::initializer_list<V> list,
0208 typename boost::enable_if<
0209 boost::is_convertible<std::initializer_list<V>,key_type> >::type* =0):
0210 h(core::insert(list)){}
0211 #endif
0212
0213 flyweight(const flyweight& x)BOOST_NOEXCEPT:h(x.h){}
0214 flyweight(flyweight& x)BOOST_NOEXCEPT:h(x.h){}
0215
0216 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
0217 flyweight(const flyweight&& x)BOOST_NOEXCEPT:h(x.h){}
0218 flyweight(flyweight&& x)BOOST_NOEXCEPT:h(x.h){}
0219 #endif
0220
0221 #if !defined(BOOST_NO_SFINAE)&&!defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
0222 template<typename V>
0223 typename boost::enable_if<
0224 boost::is_convertible<std::initializer_list<V>,key_type>,flyweight&>::type
0225 operator=(std::initializer_list<V> list)
0226 {
0227 return operator=(flyweight(list));
0228 }
0229 #endif
0230
0231 flyweight& operator=(const flyweight& x)BOOST_NOEXCEPT{h=x.h;return *this;}
0232 flyweight& operator=(const value_type& x){return operator=(flyweight(x));}
0233
0234 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
0235 flyweight& operator=(value_type&& x)
0236 {
0237 return operator=(flyweight(std::move(x)));
0238 }
0239 #endif
0240
0241
0242
0243 const key_type& get_key()const
0244 BOOST_NOEXCEPT_IF(noexcept(core::key(boost::declval<const handle_type&>())))
0245 {
0246 return core::key(h);
0247 }
0248
0249 const value_type& get()const BOOST_NOEXCEPT{return core::value(h);}
0250 const value_type& operator*()const BOOST_NOEXCEPT{return get();}
0251 operator const value_type&()const BOOST_NOEXCEPT{return get();}
0252 const value_type* operator->()const BOOST_NOEXCEPT
0253 {return boost::addressof(get());}
0254
0255
0256
0257 friend bool operator==(const flyweight& x,const flyweight& y)BOOST_NOEXCEPT
0258 {
0259 #if BOOST_WORKAROUND(BOOST_MSVC,<1930)
0260
0261
0262
0263
0264 return
0265 boost::addressof(core::value(x.h))==boost::addressof(core::value(y.h));
0266 #else
0267 return boost::addressof(x.get())==boost::addressof(y.get());
0268 #endif
0269 }
0270
0271 friend bool operator!=(const flyweight& x,const flyweight& y)BOOST_NOEXCEPT
0272 {
0273 return !(x==y);
0274 }
0275
0276
0277
0278 void swap(flyweight& x)BOOST_NOEXCEPT{boost::core::invoke_swap(h,x.h);}
0279
0280 private:
0281 handle_type h;
0282 };
0283
0284 #define BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(n) \
0285 typename Arg##n##1,typename Arg##n##2,typename Arg##n##3, \
0286 typename Arg##n##4,typename Arg##n##5
0287 #define BOOST_FLYWEIGHT_TEMPL_ARGS(n) \
0288 Arg##n##1,Arg##n##2,Arg##n##3,Arg##n##4,Arg##n##5
0289
0290
0291
0292
0293
0294 template<
0295 typename T1,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(1),
0296 typename T2,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(2)
0297 >
0298 bool operator==(
0299 const flyweight<T1,BOOST_FLYWEIGHT_TEMPL_ARGS(1)>& x,
0300 const flyweight<T2,BOOST_FLYWEIGHT_TEMPL_ARGS(2)>& y)
0301 {
0302 return x.get()==y.get();
0303 }
0304
0305 template<
0306 typename T1,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(1),
0307 typename T2,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(2)
0308 >
0309 bool operator<(
0310 const flyweight<T1,BOOST_FLYWEIGHT_TEMPL_ARGS(1)>& x,
0311 const flyweight<T2,BOOST_FLYWEIGHT_TEMPL_ARGS(2)>& y)
0312 {
0313 return x.get()<y.get();
0314 }
0315
0316 #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
0317 template<
0318 typename T1,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(1),
0319 typename T2
0320 >
0321 bool operator==(
0322 const flyweight<T1,BOOST_FLYWEIGHT_TEMPL_ARGS(1)>& x,const T2& y)
0323 {
0324 return x.get()==y;
0325 }
0326
0327 template<
0328 typename T1,
0329 typename T2,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(2)
0330 >
0331 bool operator==(
0332 const T1& x,const flyweight<T2,BOOST_FLYWEIGHT_TEMPL_ARGS(2)>& y)
0333 {
0334 return x==y.get();
0335 }
0336
0337 template<
0338 typename T1,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(1),
0339 typename T2
0340 >
0341 bool operator<(
0342 const flyweight<T1,BOOST_FLYWEIGHT_TEMPL_ARGS(1)>& x,const T2& y)
0343 {
0344 return x.get()<y;
0345 }
0346
0347 template<
0348 typename T1,
0349 typename T2,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(2)
0350 >
0351 bool operator<(
0352 const T1& x,const flyweight<T2,BOOST_FLYWEIGHT_TEMPL_ARGS(2)>& y)
0353 {
0354 return x<y.get();
0355 }
0356 #endif
0357
0358
0359
0360 #define BOOST_FLYWEIGHT_COMPLETE_COMP_OPS(t,a1,a2) \
0361 template<t> \
0362 inline bool operator!=(const a1& x,const a2& y) \
0363 { \
0364 return !(x==y); \
0365 } \
0366 \
0367 template<t> \
0368 inline bool operator>(const a1& x,const a2& y) \
0369 { \
0370 return y<x; \
0371 } \
0372 \
0373 template<t> \
0374 inline bool operator>=(const a1& x,const a2& y) \
0375 { \
0376 return !(x<y); \
0377 } \
0378 \
0379 template<t> \
0380 inline bool operator<=(const a1& x,const a2& y) \
0381 { \
0382 return !(y<x); \
0383 }
0384
0385 BOOST_FLYWEIGHT_COMPLETE_COMP_OPS(
0386 typename T1 BOOST_PP_COMMA()
0387 BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(1) BOOST_PP_COMMA()
0388 typename T2 BOOST_PP_COMMA()
0389 BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(2),
0390 flyweight<
0391 T1 BOOST_PP_COMMA() BOOST_FLYWEIGHT_TEMPL_ARGS(1)
0392 >,
0393 flyweight<
0394 T2 BOOST_PP_COMMA() BOOST_FLYWEIGHT_TEMPL_ARGS(2)
0395 >)
0396
0397 #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
0398 BOOST_FLYWEIGHT_COMPLETE_COMP_OPS(
0399 typename T1 BOOST_PP_COMMA()
0400 BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(1) BOOST_PP_COMMA()
0401 typename T2,
0402 flyweight<
0403 T1 BOOST_PP_COMMA() BOOST_FLYWEIGHT_TEMPL_ARGS(1)
0404 >,
0405 T2)
0406
0407 BOOST_FLYWEIGHT_COMPLETE_COMP_OPS(
0408 typename T1 BOOST_PP_COMMA()
0409 typename T2 BOOST_PP_COMMA()
0410 BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(2),
0411 T1,
0412 flyweight<
0413 T2 BOOST_PP_COMMA() BOOST_FLYWEIGHT_TEMPL_ARGS(2)
0414 >)
0415 #endif
0416
0417
0418
0419 template<typename T,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(_)>
0420 void swap(
0421 flyweight<T,BOOST_FLYWEIGHT_TEMPL_ARGS(_)>& x,
0422 flyweight<T,BOOST_FLYWEIGHT_TEMPL_ARGS(_)>& y)BOOST_NOEXCEPT
0423 {
0424 x.swap(y);
0425 }
0426
0427 template<
0428 BOOST_TEMPLATED_STREAM_ARGS(ElemType,Traits)
0429 BOOST_TEMPLATED_STREAM_COMMA
0430 typename T,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(_)
0431 >
0432 BOOST_TEMPLATED_STREAM(ostream,ElemType,Traits)& operator<<(
0433 BOOST_TEMPLATED_STREAM(ostream,ElemType,Traits)& out,
0434 const flyweight<T,BOOST_FLYWEIGHT_TEMPL_ARGS(_)>& x)
0435 {
0436 return out<<x.get();
0437 }
0438
0439 template<
0440 BOOST_TEMPLATED_STREAM_ARGS(ElemType,Traits)
0441 BOOST_TEMPLATED_STREAM_COMMA
0442 typename T,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(_)
0443 >
0444 BOOST_TEMPLATED_STREAM(istream,ElemType,Traits)& operator>>(
0445 BOOST_TEMPLATED_STREAM(istream,ElemType,Traits)& in,
0446 flyweight<T,BOOST_FLYWEIGHT_TEMPL_ARGS(_)>& x)
0447 {
0448 typedef typename flyweight<
0449 T,BOOST_FLYWEIGHT_TEMPL_ARGS(_)
0450 >::value_type value_type;
0451
0452
0453 value_type t(x.get());
0454 in>>t;
0455 x=t;
0456 return in;
0457 }
0458
0459 }
0460
0461 }
0462
0463 #if !defined(BOOST_FLYWEIGHT_DISABLE_HASH_SUPPORT)
0464
0465
0466
0467 #if !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL)
0468 namespace std{
0469
0470 template<typename T,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(_)>
0471 BOOST_FLYWEIGHT_STD_HASH_STRUCT_KEYWORD
0472 hash<boost::flyweight<T,BOOST_FLYWEIGHT_TEMPL_ARGS(_)> >
0473 {
0474 public:
0475 typedef std::size_t result_type;
0476 typedef boost::flyweight<
0477 T,BOOST_FLYWEIGHT_TEMPL_ARGS(_)> argument_type;
0478
0479 result_type operator()(const argument_type& x)const BOOST_NOEXCEPT
0480 {
0481 typedef typename argument_type::value_type value_type;
0482
0483 std::hash<const value_type*> h;
0484 return h(boost::addressof(x.get()));
0485 }
0486 };
0487
0488 }
0489 #endif
0490
0491 namespace boost{
0492 #if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
0493 namespace flyweights{
0494 #endif
0495
0496 template<typename T,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(_)>
0497 std::size_t
0498 hash_value(const flyweight<T,BOOST_FLYWEIGHT_TEMPL_ARGS(_)>& x)BOOST_NOEXCEPT
0499 {
0500 typedef typename flyweight<
0501 T,BOOST_FLYWEIGHT_TEMPL_ARGS(_)
0502 >::value_type value_type;
0503
0504 boost::hash<const value_type*> h;
0505 return h(boost::addressof(x.get()));
0506 }
0507
0508 #if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
0509 }
0510 #endif
0511 }
0512 #endif
0513
0514 #undef BOOST_FLYWEIGHT_COMPLETE_COMP_OPS
0515 #undef BOOST_FLYWEIGHT_TEMPL_ARGS
0516 #undef BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS
0517
0518 #if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1400))
0519 #pragma warning(pop)
0520 #endif
0521
0522 #endif