Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-18 08:37:44

0001 /* Copyright 2006-2024 Joaquin M Lopez Munoz.
0002  * Distributed under the Boost Software License, Version 1.0.
0003  * (See accompanying file LICENSE_1_0.txt or copy at
0004  * http://www.boost.org/LICENSE_1_0.txt)
0005  *
0006  * See http://www.boost.org/libs/flyweight for library home page.
0007  */
0008 
0009 #ifndef BOOST_FLYWEIGHT_KEY_VALUE_HPP
0010 #define BOOST_FLYWEIGHT_KEY_VALUE_HPP
0011 
0012 #if defined(_MSC_VER)
0013 #pragma once
0014 #endif
0015 
0016 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
0017 #include <boost/assert.hpp>
0018 #include <boost/config/workaround.hpp>
0019 #include <boost/flyweight/detail/perfect_fwd.hpp>
0020 #include <boost/flyweight/detail/value_tag.hpp>
0021 #include <boost/flyweight/key_value_fwd.hpp>
0022 #include <boost/mpl/assert.hpp>
0023 #include <boost/type_traits/aligned_storage.hpp>
0024 #include <boost/type_traits/alignment_of.hpp> 
0025 #include <boost/type_traits/declval.hpp>
0026 #include <boost/type_traits/is_same.hpp>
0027 #include <new>
0028 
0029 /* key-value policy: flywewight lookup is based on Key, which also serves
0030  * to construct Value only when needed (new factory entry). key_value is
0031  * used to avoid the construction of temporary values when such construction
0032  * is expensive.
0033  * Optionally, KeyFromValue extracts the key from a value, which
0034  * is needed in expressions like this:
0035  *
0036  *  typedef flyweight<key_value<Key,Value> > fw_t;
0037  *  fw_t  fw;
0038  *  Value v;
0039  *  fw=v; // no key explicitly given
0040  *
0041  * If no KeyFromValue is provided, this latter expression fails to compile.
0042  */
0043 
0044 namespace boost{
0045 
0046 namespace flyweights{
0047 
0048 namespace detail{
0049 
0050 template<typename Key,typename Value,typename KeyFromValue>
0051 struct variant_key_value:value_marker
0052 {
0053   typedef Key   key_type;
0054   typedef Value value_type;
0055 
0056   class rep_type
0057   {
0058   public:
0059     /* template ctors */
0060 
0061 #define BOOST_FLYWEIGHT_PERFECT_FWD_CTR_BODY(args)       \
0062   :value_cted(false)                                     \
0063 {                                                        \
0064   new(key_ptr())key_type(BOOST_FLYWEIGHT_FORWARD(args)); \
0065 }
0066 
0067   BOOST_FLYWEIGHT_PERFECT_FWD(
0068     explicit rep_type,
0069     BOOST_FLYWEIGHT_PERFECT_FWD_CTR_BODY)
0070 
0071 #undef BOOST_FLYWEIGHT_PERFECT_FWD_CTR_BODY
0072 
0073     rep_type(const rep_type& x):value_cted(false)
0074     {
0075       if(!x.value_cted)new(key_ptr())key_type(*x.key_ptr());
0076       else            new(key_ptr())key_type(key_from_value(*x.value_ptr()));
0077     }
0078 
0079     rep_type(const value_type& x):value_cted(false)
0080     {
0081       new(key_ptr())key_type(key_from_value(x));
0082     }
0083 
0084 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
0085     rep_type(rep_type&& x):value_cted(false)
0086     {
0087       if(!x.value_cted)new(key_ptr())key_type(std::move(*x.key_ptr()));
0088       else             new(key_ptr())key_type(key_from_value(*x.value_ptr()));
0089     }
0090 
0091     rep_type(value_type&& x):value_cted(false)
0092     {
0093       new(key_ptr())key_type(key_from_value(x));
0094     }
0095 #endif
0096 
0097     ~rep_type()
0098     {
0099       if(value_cted)value_ptr()->~value_type();
0100       else          key_ptr()->~key_type();
0101     }
0102 
0103     operator const key_type&()const
0104     BOOST_NOEXCEPT_IF(noexcept(
0105       boost::declval<KeyFromValue>()(boost::declval<const value_type&>())))
0106     {
0107       if(value_cted)return key_from_value(*value_ptr());
0108       else          return *key_ptr();
0109     }
0110 
0111     operator const value_type&()const
0112     {
0113       BOOST_ASSERT(value_cted);
0114       return *value_ptr();
0115     }
0116 
0117   private:
0118     friend struct variant_key_value;
0119 
0120     key_type* key_ptr()const
0121     {
0122       return static_cast<key_type*>(static_cast<void*>(&key_spc));
0123     }
0124 
0125     value_type* value_ptr()const
0126     {
0127       return static_cast<value_type*>(static_cast<void*>(&value_spc));
0128     }
0129 
0130     static const key_type& key_from_value(const value_type& x)
0131     {
0132       KeyFromValue k;
0133       return k(x);
0134     }
0135 
0136     void key_construct_value()const
0137     {
0138       if(!value_cted){
0139         new(value_ptr())value_type(*key_ptr());
0140         key_ptr()->~key_type();
0141         value_cted=true;
0142       }
0143     }
0144 
0145     void copy_construct_value(const value_type& x)const
0146     {
0147       if(!value_cted){
0148         new(value_ptr())value_type(x);
0149         key_ptr()->~key_type();
0150         value_cted=true;
0151       }
0152     }
0153 
0154 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
0155     void move_construct_value(value_type&& x)const
0156     {
0157       if(!value_cted){
0158         new(value_ptr())value_type(std::move(x));
0159         key_ptr()->~key_type();
0160         value_cted=true;
0161       }
0162     }
0163 #endif
0164 
0165     mutable typename boost::aligned_storage<
0166       sizeof(key_type),
0167       boost::alignment_of<key_type>::value
0168     >::type                                    key_spc;
0169     mutable typename boost::aligned_storage<
0170       sizeof(value_type),
0171       boost::alignment_of<value_type>::value
0172     >::type                                    value_spc;
0173     mutable bool                               value_cted;
0174   };
0175 
0176   static void key_construct_value(const rep_type& r)
0177   {
0178     r.key_construct_value();
0179   }
0180 
0181   static void copy_construct_value(const rep_type& r,const value_type& x)
0182   {
0183     r.copy_construct_value(x);
0184   }
0185 
0186 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
0187   static void move_construct_value(const rep_type& r,value_type&& x)
0188   {
0189     r.move_construct_value(std::move(x));
0190   }
0191 #endif
0192 };
0193 
0194 template<typename Key,typename Value>
0195 struct product_key_value:value_marker
0196 {
0197   typedef Key   key_type;
0198   typedef Value value_type;
0199 
0200   class rep_type
0201   {
0202   public:
0203     /* template ctors */
0204 
0205 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)&&\
0206     !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)&&\
0207     BOOST_WORKAROUND(__GNUC__,<=4)&&(__GNUC__<4||__GNUC_MINOR__<=4)
0208 
0209 /* GCC 4.4.2 (and probably prior) bug: the default ctor generated by the
0210  * variadic temmplate ctor below fails to value-initialize key.
0211  */
0212 
0213     rep_type():key(),value_cted(false){}
0214 #endif
0215 
0216 #define BOOST_FLYWEIGHT_PERFECT_FWD_CTR_BODY(args) \
0217   :key(BOOST_FLYWEIGHT_FORWARD(args)),value_cted(false){}
0218 
0219   BOOST_FLYWEIGHT_PERFECT_FWD(
0220     explicit rep_type,
0221     BOOST_FLYWEIGHT_PERFECT_FWD_CTR_BODY)
0222 
0223 #undef BOOST_FLYWEIGHT_PERFECT_FWD_CTR_BODY
0224 
0225     rep_type(const rep_type& x):key(x.key),value_cted(false){}
0226     rep_type(const value_type&):key(no_key_from_value_failure()){}
0227 
0228 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
0229     rep_type(rep_type&& x):key(std::move(x.key)),value_cted(false){}
0230     rep_type(value_type&&):key(no_key_from_value_failure()){}
0231 #endif
0232 
0233     ~rep_type()
0234     {
0235       if(value_cted)value_ptr()->~value_type();
0236     }
0237 
0238     operator const key_type&()const BOOST_NOEXCEPT{return key;}
0239 
0240     operator const value_type&()const
0241     {
0242       BOOST_ASSERT(value_cted);
0243       return *value_ptr();
0244     }
0245 
0246   private:
0247     friend struct product_key_value;
0248 
0249     value_type* value_ptr()const
0250     {
0251       return static_cast<value_type*>(static_cast<void*>(&value_spc));
0252     }
0253 
0254     struct no_key_from_value_failure
0255     {
0256       BOOST_MPL_ASSERT_MSG(
0257         false,
0258         NO_KEY_FROM_VALUE_CONVERSION_PROVIDED,
0259         (key_type,value_type));
0260 
0261       operator const key_type&()const;
0262     };
0263 
0264     void key_construct_value()const
0265     {
0266       if(!value_cted){
0267         new(value_ptr())value_type(key);
0268         value_cted=true;
0269       }
0270     }
0271 
0272     key_type                                 key;
0273     mutable typename boost::aligned_storage<
0274       sizeof(value_type),
0275       boost::alignment_of<value_type>::value
0276     >::type                                  value_spc;
0277     mutable bool                             value_cted;
0278   };
0279 
0280   static void key_construct_value(const rep_type& r)
0281   {
0282     r.key_construct_value();
0283   }
0284 
0285   /* [copy|move]_construct_value() can't really ever be called, provided to
0286    * avoid compile errors (it is the no_key_from_value_failure compile error
0287    * we want to appear in these cases).
0288    */
0289 
0290   static void copy_construct_value(const rep_type&,const value_type&){}
0291 
0292 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
0293   static void move_construct_value(const rep_type&,value_type&&){}
0294 #endif
0295 };
0296 
0297 } /* namespace flyweights::detail */
0298 
0299 template<typename Key,typename Value,typename KeyFromValue>
0300 struct key_value:
0301   mpl::if_<
0302     is_same<KeyFromValue,no_key_from_value>,
0303     detail::product_key_value<Key,Value>,
0304     detail::variant_key_value<Key,Value,KeyFromValue>
0305   >::type
0306 {};
0307 
0308 } /* namespace flyweights */
0309 
0310 } /* namespace boost */
0311 
0312 #endif