File indexing completed on 2025-09-18 08:37:44
0001
0002
0003
0004
0005
0006
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
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
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
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
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
0210
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
0286
0287
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 }
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 }
0309
0310 }
0311
0312 #endif