Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 09:45:31

0001 /* Flyweight class. 
0002  *
0003  * Copyright 2006-2024 Joaquin M Lopez Munoz.
0004  * Distributed under the Boost Software License, Version 1.0.
0005  * (See accompanying file LICENSE_1_0.txt or copy at
0006  * http://www.boost.org/LICENSE_1_0.txt)
0007  *
0008  * See http://www.boost.org/libs/flyweight for library home page.
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)  /* multiple default ctors */
0052 #pragma warning(disable:4521)  /* multiple copy ctors */
0053 #endif
0054 
0055 namespace boost{
0056   
0057 namespace flyweights{
0058 
0059 namespace detail{
0060 
0061 /* Used for the detection of unmatched template args in a
0062  * flyweight instantiation.
0063  */
0064 
0065 struct unmatched_arg;
0066 
0067 /* Boost.Parameter structures for use in flyweight.
0068  * NB: these types are derived from instead of typedef'd to force their
0069  * instantiation, which solves http://bugs.sun.com/view_bug.do?bug_id=6782987
0070  * as found out by Simon Atanasyan.
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 } /* namespace flyweights::detail */
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   /* You have passed a type in the specification of a flyweight type that
0161    * could not be interpreted as a valid argument.
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   /* static data initialization */
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   /* construct/copy/destroy */
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   /* convertibility to underlying type */
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   /* exact type equality  */
0256     
0257   friend bool operator==(const flyweight& x,const flyweight& y)BOOST_NOEXCEPT
0258   {
0259 #if BOOST_WORKAROUND(BOOST_MSVC,<1930)
0260     /* msvc 14.0 has spurious codegen bugs seemingly related to flyweight::get
0261      * being noexcept.
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   /* modifiers */
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 /* Comparison. Unlike exact type comparison defined above, intertype
0291  * comparison just forwards to the underlying objects.
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 /* !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) */
0357 
0358 /* rest of comparison operators */
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 /* !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) */
0416 
0417 /* specialized algorithms */
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   /* value_type need not be default ctble but must be copy ctble */
0453   value_type t(x.get());
0454   in>>t;
0455   x=t;
0456   return in;
0457 }
0458 
0459 } /* namespace flyweights */
0460 
0461 } /* namespace boost */
0462 
0463 #if !defined(BOOST_FLYWEIGHT_DISABLE_HASH_SUPPORT)
0464 
0465 /* hash support */
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 } /* namespace std */
0489 #endif /* !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL) */
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 } /* namespace flyweights */
0510 #endif
0511 } /* namespace boost */
0512 #endif /* !defined(BOOST_FLYWEIGHT_DISABLE_HASH_SUPPORT) */
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