File indexing completed on 2025-01-18 09:30:53
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/detail/workaround.hpp>
0018 #include <boost/flyweight/detail/perfect_fwd.hpp>
0019 #include <boost/flyweight/detail/value_tag.hpp>
0020 #include <boost/flyweight/key_value_fwd.hpp>
0021 #include <boost/mpl/assert.hpp>
0022 #include <boost/type_traits/aligned_storage.hpp>
0023 #include <boost/type_traits/alignment_of.hpp>
0024 #include <boost/type_traits/is_same.hpp>
0025 #include <new>
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042 namespace boost{
0043
0044 namespace flyweights{
0045
0046 namespace detail{
0047
0048 template<typename Key,typename Value,typename KeyFromValue>
0049 struct optimized_key_value:value_marker
0050 {
0051 typedef Key key_type;
0052 typedef Value value_type;
0053
0054 class rep_type
0055 {
0056 public:
0057
0058
0059 #define BOOST_FLYWEIGHT_PERFECT_FWD_CTR_BODY(args) \
0060 :value_ptr(0) \
0061 { \
0062 new(spc_ptr())key_type(BOOST_FLYWEIGHT_FORWARD(args)); \
0063 }
0064
0065 BOOST_FLYWEIGHT_PERFECT_FWD(
0066 explicit rep_type,
0067 BOOST_FLYWEIGHT_PERFECT_FWD_CTR_BODY)
0068
0069 #undef BOOST_FLYWEIGHT_PERFECT_FWD_CTR_BODY
0070
0071 rep_type(const rep_type& x):value_ptr(x.value_ptr)
0072 {
0073 if(!x.value_ptr)new(key_ptr())key_type(*x.key_ptr());
0074 }
0075
0076 rep_type(const value_type& x):value_ptr(&x){}
0077
0078 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
0079 rep_type(rep_type&& x):value_ptr(x.value_ptr)
0080 {
0081 if(!x.value_ptr)new(key_ptr())key_type(std::move(*x.key_ptr()));
0082 }
0083
0084 rep_type(value_type&& x):value_ptr(&x){}
0085 #endif
0086
0087 ~rep_type()
0088 {
0089 if(!value_ptr) key_ptr()->~key_type();
0090 else if(value_cted())value_ptr->~value_type();
0091 }
0092
0093 operator const key_type&()const
0094 {
0095 if(value_ptr)return key_from_value(*value_ptr);
0096 else return *key_ptr();
0097 }
0098
0099 operator const value_type&()const
0100 {
0101
0102
0103
0104
0105
0106 return *static_cast<value_type*>(spc_ptr());
0107 }
0108
0109 private:
0110 friend struct optimized_key_value;
0111
0112 void* spc_ptr()const{return static_cast<void*>(&spc);}
0113 bool value_cted()const{return value_ptr==spc_ptr();}
0114
0115 key_type* key_ptr()const
0116 {
0117 return static_cast<key_type*>(static_cast<void*>(&spc));
0118 }
0119
0120 static const key_type& key_from_value(const value_type& x)
0121 {
0122 KeyFromValue k;
0123 return k(x);
0124 }
0125
0126 void construct_value()const
0127 {
0128 if(!value_cted()){
0129
0130
0131 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
0132 key_type k(std::move(*key_ptr()));
0133 #else
0134 key_type k(*key_ptr());
0135 #endif
0136
0137 key_ptr()->~key_type();
0138 value_ptr=
0139 static_cast<value_type*>(spc_ptr())+1;
0140 value_ptr=new(spc_ptr())value_type(k);
0141 }
0142 }
0143
0144 void copy_value()const
0145 {
0146 if(!value_cted())value_ptr=new(spc_ptr())value_type(*value_ptr);
0147 }
0148
0149 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
0150 void move_value()const
0151 {
0152 if(!value_cted())value_ptr=
0153 new(spc_ptr())value_type(std::move(const_cast<value_type&>(*value_ptr)));
0154 }
0155 #endif
0156
0157 mutable typename boost::aligned_storage<
0158 (sizeof(key_type)>sizeof(value_type))?
0159 sizeof(key_type):sizeof(value_type),
0160 (boost::alignment_of<key_type>::value >
0161 boost::alignment_of<value_type>::value)?
0162 boost::alignment_of<key_type>::value:
0163 boost::alignment_of<value_type>::value
0164 >::type spc;
0165 mutable const value_type* value_ptr;
0166 };
0167
0168 static void construct_value(const rep_type& r)
0169 {
0170 r.construct_value();
0171 }
0172
0173 static void copy_value(const rep_type& r)
0174 {
0175 r.copy_value();
0176 }
0177
0178 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
0179 static void move_value(const rep_type& r)
0180 {
0181 r.move_value();
0182 }
0183 #endif
0184 };
0185
0186 template<typename Key,typename Value>
0187 struct regular_key_value:value_marker
0188 {
0189 typedef Key key_type;
0190 typedef Value value_type;
0191
0192 class rep_type
0193 {
0194 public:
0195
0196
0197 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)&&\
0198 !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)&&\
0199 BOOST_WORKAROUND(__GNUC__,<=4)&&(__GNUC__<4||__GNUC_MINOR__<=4)
0200
0201
0202
0203
0204
0205 rep_type():key(),value_ptr(0){}
0206 #endif
0207
0208 #define BOOST_FLYWEIGHT_PERFECT_FWD_CTR_BODY(args) \
0209 :key(BOOST_FLYWEIGHT_FORWARD(args)),value_ptr(0){}
0210
0211 BOOST_FLYWEIGHT_PERFECT_FWD(
0212 explicit rep_type,
0213 BOOST_FLYWEIGHT_PERFECT_FWD_CTR_BODY)
0214
0215 #undef BOOST_FLYWEIGHT_PERFECT_FWD_CTR_BODY
0216
0217 rep_type(const rep_type& x):key(x.key),value_ptr(0){}
0218 rep_type(const value_type&):key(no_key_from_value_failure()){}
0219
0220 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
0221 rep_type(rep_type&& x):key(std::move(x.key)),value_ptr(0){}
0222 rep_type(value_type&&):key(no_key_from_value_failure()){}
0223 #endif
0224
0225 ~rep_type()
0226 {
0227 if(value_ptr)value_ptr->~value_type();
0228 }
0229
0230 operator const key_type&()const{return key;}
0231
0232 operator const value_type&()const
0233 {
0234
0235
0236
0237
0238 return *static_cast<value_type*>(spc_ptr());
0239 }
0240
0241 private:
0242 friend struct regular_key_value;
0243
0244 void* spc_ptr()const{return static_cast<void*>(&spc);}
0245
0246 struct no_key_from_value_failure
0247 {
0248 BOOST_MPL_ASSERT_MSG(
0249 false,
0250 NO_KEY_FROM_VALUE_CONVERSION_PROVIDED,
0251 (key_type,value_type));
0252
0253 operator const key_type&()const;
0254 };
0255
0256 void construct_value()const
0257 {
0258 if(!value_ptr)value_ptr=new(spc_ptr())value_type(key);
0259 }
0260
0261 key_type key;
0262 mutable typename boost::aligned_storage<
0263 sizeof(value_type),
0264 boost::alignment_of<value_type>::value
0265 >::type spc;
0266 mutable const value_type* value_ptr;
0267 };
0268
0269 static void construct_value(const rep_type& r)
0270 {
0271 r.construct_value();
0272 }
0273
0274
0275
0276
0277
0278
0279 static void copy_value(const rep_type&){}
0280
0281 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
0282 static void move_value(const rep_type&){}
0283 #endif
0284 };
0285
0286 }
0287
0288 template<typename Key,typename Value,typename KeyFromValue>
0289 struct key_value:
0290 mpl::if_<
0291 is_same<KeyFromValue,no_key_from_value>,
0292 detail::regular_key_value<Key,Value>,
0293 detail::optimized_key_value<Key,Value,KeyFromValue>
0294 >::type
0295 {};
0296
0297 }
0298
0299 }
0300
0301 #endif