annotate DEPENDENCIES/generic/include/boost/flyweight/key_value.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents c530137014c0
children
rev   line source
Chris@101 1 /* Copyright 2006-2014 Joaquin M Lopez Munoz.
Chris@16 2 * Distributed under the Boost Software License, Version 1.0.
Chris@16 3 * (See accompanying file LICENSE_1_0.txt or copy at
Chris@16 4 * http://www.boost.org/LICENSE_1_0.txt)
Chris@16 5 *
Chris@16 6 * See http://www.boost.org/libs/flyweight for library home page.
Chris@16 7 */
Chris@16 8
Chris@16 9 #ifndef BOOST_FLYWEIGHT_KEY_VALUE_HPP
Chris@16 10 #define BOOST_FLYWEIGHT_KEY_VALUE_HPP
Chris@16 11
Chris@101 12 #if defined(_MSC_VER)
Chris@16 13 #pragma once
Chris@16 14 #endif
Chris@16 15
Chris@101 16 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
Chris@101 17 #include <boost/detail/workaround.hpp>
Chris@101 18 #include <boost/flyweight/detail/perfect_fwd.hpp>
Chris@16 19 #include <boost/flyweight/detail/value_tag.hpp>
Chris@16 20 #include <boost/flyweight/key_value_fwd.hpp>
Chris@16 21 #include <boost/mpl/assert.hpp>
Chris@16 22 #include <boost/type_traits/aligned_storage.hpp>
Chris@16 23 #include <boost/type_traits/alignment_of.hpp>
Chris@16 24 #include <boost/type_traits/is_same.hpp>
Chris@16 25 #include <new>
Chris@16 26
Chris@16 27 /* key-value policy: flywewight lookup is based on Key, which also serves
Chris@16 28 * to construct Value only when needed (new factory entry). key_value is
Chris@16 29 * used to avoid the construction of temporary values when such construction
Chris@16 30 * is expensive.
Chris@16 31 * Optionally, KeyFromValue extracts the key from a value, which
Chris@16 32 * is needed in expressions like this:
Chris@16 33 *
Chris@16 34 * typedef flyweight<key_value<Key,Value> > fw_t;
Chris@16 35 * fw_t fw;
Chris@16 36 * Value v;
Chris@16 37 * fw=v; // no key explicitly given
Chris@16 38 *
Chris@16 39 * If no KeyFromValue is provided, this latter expression fails to compile.
Chris@16 40 */
Chris@16 41
Chris@16 42 namespace boost{
Chris@16 43
Chris@16 44 namespace flyweights{
Chris@16 45
Chris@16 46 namespace detail{
Chris@16 47
Chris@16 48 template<typename Key,typename Value,typename KeyFromValue>
Chris@16 49 struct optimized_key_value:value_marker
Chris@16 50 {
Chris@16 51 typedef Key key_type;
Chris@16 52 typedef Value value_type;
Chris@16 53
Chris@16 54 class rep_type
Chris@16 55 {
Chris@16 56 public:
Chris@16 57 /* template ctors */
Chris@16 58
Chris@101 59 #define BOOST_FLYWEIGHT_PERFECT_FWD_CTR_BODY(args) \
Chris@101 60 :value_ptr(0) \
Chris@101 61 { \
Chris@101 62 new(spc_ptr())key_type(BOOST_FLYWEIGHT_FORWARD(args)); \
Chris@16 63 }
Chris@16 64
Chris@101 65 BOOST_FLYWEIGHT_PERFECT_FWD(
Chris@101 66 explicit rep_type,
Chris@101 67 BOOST_FLYWEIGHT_PERFECT_FWD_CTR_BODY)
Chris@101 68
Chris@101 69 #undef BOOST_FLYWEIGHT_PERFECT_FWD_CTR_BODY
Chris@16 70
Chris@16 71 rep_type(const rep_type& x):value_ptr(x.value_ptr)
Chris@16 72 {
Chris@16 73 if(!x.value_ptr)new(key_ptr())key_type(*x.key_ptr());
Chris@16 74 }
Chris@16 75
Chris@101 76 rep_type(const value_type& x):value_ptr(&x){}
Chris@101 77
Chris@101 78 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
Chris@101 79 rep_type(rep_type&& x):value_ptr(x.value_ptr)
Chris@101 80 {
Chris@101 81 if(!x.value_ptr)new(key_ptr())key_type(std::move(*x.key_ptr()));
Chris@101 82 }
Chris@101 83
Chris@101 84 rep_type(value_type&& x):value_ptr(&x){}
Chris@101 85 #endif
Chris@101 86
Chris@16 87 ~rep_type()
Chris@16 88 {
Chris@16 89 if(!value_ptr) key_ptr()->~key_type();
Chris@16 90 else if(value_cted())value_ptr->~value_type();
Chris@16 91 }
Chris@16 92
Chris@16 93 operator const key_type&()const
Chris@16 94 {
Chris@16 95 if(value_ptr)return key_from_value(*value_ptr);
Chris@16 96 else return *key_ptr();
Chris@16 97 }
Chris@16 98
Chris@16 99 operator const value_type&()const
Chris@16 100 {
Chris@16 101 /* This is always called after construct_value() or copy_value(),
Chris@16 102 * so we access spc directly rather than through value_ptr to
Chris@16 103 * save us an indirection.
Chris@16 104 */
Chris@16 105
Chris@16 106 return *static_cast<value_type*>(spc_ptr());
Chris@16 107 }
Chris@16 108
Chris@16 109 private:
Chris@16 110 friend struct optimized_key_value;
Chris@16 111
Chris@16 112 void* spc_ptr()const{return static_cast<void*>(&spc);}
Chris@16 113 bool value_cted()const{return value_ptr==spc_ptr();}
Chris@16 114
Chris@16 115 key_type* key_ptr()const
Chris@16 116 {
Chris@16 117 return static_cast<key_type*>(static_cast<void*>(&spc));
Chris@16 118 }
Chris@16 119
Chris@16 120 static const key_type& key_from_value(const value_type& x)
Chris@16 121 {
Chris@16 122 KeyFromValue k;
Chris@16 123 return k(x);
Chris@16 124 }
Chris@16 125
Chris@16 126 void construct_value()const
Chris@16 127 {
Chris@16 128 if(!value_cted()){
Chris@16 129 /* value_ptr must be ==0, oherwise copy_value would have been called */
Chris@16 130
Chris@101 131 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
Chris@101 132 key_type k(std::move(*key_ptr()));
Chris@101 133 #else
Chris@16 134 key_type k(*key_ptr());
Chris@101 135 #endif
Chris@101 136
Chris@16 137 key_ptr()->~key_type();
Chris@16 138 value_ptr= /* guarantees key won't be re-dted at ~rep_type if the */
Chris@16 139 static_cast<value_type*>(spc_ptr())+1; /* next statement throws */
Chris@16 140 value_ptr=new(spc_ptr())value_type(k);
Chris@16 141 }
Chris@16 142 }
Chris@16 143
Chris@16 144 void copy_value()const
Chris@16 145 {
Chris@16 146 if(!value_cted())value_ptr=new(spc_ptr())value_type(*value_ptr);
Chris@16 147 }
Chris@16 148
Chris@101 149 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
Chris@101 150 void move_value()const
Chris@101 151 {
Chris@101 152 if(!value_cted())value_ptr=
Chris@101 153 new(spc_ptr())value_type(std::move(const_cast<value_type&>(*value_ptr)));
Chris@101 154 }
Chris@101 155 #endif
Chris@101 156
Chris@16 157 mutable typename boost::aligned_storage<
Chris@16 158 (sizeof(key_type)>sizeof(value_type))?
Chris@16 159 sizeof(key_type):sizeof(value_type),
Chris@16 160 (boost::alignment_of<key_type>::value >
Chris@16 161 boost::alignment_of<value_type>::value)?
Chris@16 162 boost::alignment_of<key_type>::value:
Chris@16 163 boost::alignment_of<value_type>::value
Chris@16 164 >::type spc;
Chris@16 165 mutable const value_type* value_ptr;
Chris@16 166 };
Chris@16 167
Chris@16 168 static void construct_value(const rep_type& r)
Chris@16 169 {
Chris@16 170 r.construct_value();
Chris@16 171 }
Chris@16 172
Chris@16 173 static void copy_value(const rep_type& r)
Chris@16 174 {
Chris@16 175 r.copy_value();
Chris@16 176 }
Chris@101 177
Chris@101 178 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
Chris@101 179 static void move_value(const rep_type& r)
Chris@101 180 {
Chris@101 181 r.move_value();
Chris@101 182 }
Chris@101 183 #endif
Chris@16 184 };
Chris@16 185
Chris@16 186 template<typename Key,typename Value>
Chris@16 187 struct regular_key_value:value_marker
Chris@16 188 {
Chris@16 189 typedef Key key_type;
Chris@16 190 typedef Value value_type;
Chris@16 191
Chris@16 192 class rep_type
Chris@16 193 {
Chris@16 194 public:
Chris@16 195 /* template ctors */
Chris@16 196
Chris@101 197 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)&&\
Chris@101 198 !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)&&\
Chris@101 199 BOOST_WORKAROUND(__GNUC__,<=4)&&(__GNUC__<4||__GNUC_MINOR__<=4)
Chris@16 200
Chris@101 201 /* GCC 4.4.2 (and probably prior) bug: the default ctor generated by the
Chris@101 202 * variadic temmplate ctor below fails to value-initialize key.
Chris@101 203 */
Chris@101 204
Chris@101 205 rep_type():key(),value_ptr(0){}
Chris@101 206 #endif
Chris@101 207
Chris@101 208 #define BOOST_FLYWEIGHT_PERFECT_FWD_CTR_BODY(args) \
Chris@101 209 :key(BOOST_FLYWEIGHT_FORWARD(args)),value_ptr(0){}
Chris@101 210
Chris@101 211 BOOST_FLYWEIGHT_PERFECT_FWD(
Chris@101 212 explicit rep_type,
Chris@101 213 BOOST_FLYWEIGHT_PERFECT_FWD_CTR_BODY)
Chris@101 214
Chris@101 215 #undef BOOST_FLYWEIGHT_PERFECT_FWD_CTR_BODY
Chris@101 216
Chris@101 217 rep_type(const rep_type& x):key(x.key),value_ptr(0){}
Chris@16 218 rep_type(const value_type& x):key(no_key_from_value_failure()){}
Chris@16 219
Chris@101 220 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
Chris@101 221 rep_type(rep_type&& x):key(std::move(x.key)),value_ptr(0){}
Chris@101 222 rep_type(value_type&& x):key(no_key_from_value_failure()){}
Chris@101 223 #endif
Chris@16 224
Chris@16 225 ~rep_type()
Chris@16 226 {
Chris@16 227 if(value_ptr)value_ptr->~value_type();
Chris@16 228 }
Chris@16 229
Chris@16 230 operator const key_type&()const{return key;}
Chris@16 231
Chris@16 232 operator const value_type&()const
Chris@16 233 {
Chris@16 234 /* This is always called after construct_value(),so we access spc
Chris@16 235 * directly rather than through value_ptr to save us an indirection.
Chris@16 236 */
Chris@16 237
Chris@16 238 return *static_cast<value_type*>(spc_ptr());
Chris@16 239 }
Chris@16 240
Chris@16 241 private:
Chris@16 242 friend struct regular_key_value;
Chris@16 243
Chris@16 244 void* spc_ptr()const{return static_cast<void*>(&spc);}
Chris@16 245
Chris@16 246 struct no_key_from_value_failure
Chris@16 247 {
Chris@16 248 BOOST_MPL_ASSERT_MSG(
Chris@16 249 false,
Chris@16 250 NO_KEY_FROM_VALUE_CONVERSION_PROVIDED,
Chris@16 251 (key_type,value_type));
Chris@16 252
Chris@16 253 operator const key_type&()const;
Chris@16 254 };
Chris@16 255
Chris@16 256 void construct_value()const
Chris@16 257 {
Chris@16 258 if(!value_ptr)value_ptr=new(spc_ptr())value_type(key);
Chris@16 259 }
Chris@16 260
Chris@16 261 key_type key;
Chris@16 262 mutable typename boost::aligned_storage<
Chris@16 263 sizeof(value_type),
Chris@16 264 boost::alignment_of<value_type>::value
Chris@16 265 >::type spc;
Chris@16 266 mutable const value_type* value_ptr;
Chris@16 267 };
Chris@16 268
Chris@16 269 static void construct_value(const rep_type& r)
Chris@16 270 {
Chris@16 271 r.construct_value();
Chris@16 272 }
Chris@16 273
Chris@101 274 /* copy_value() and move_value() can't really ever be called, provided to avoid
Chris@101 275 * compile errors (it is the no_key_from_value_failure compile error we want to
Chris@101 276 * appear in these cases).
Chris@101 277 */
Chris@101 278
Chris@16 279 static void copy_value(const rep_type&){}
Chris@101 280
Chris@101 281 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
Chris@101 282 static void move_value(const rep_type&){}
Chris@101 283 #endif
Chris@16 284 };
Chris@16 285
Chris@16 286 } /* namespace flyweights::detail */
Chris@16 287
Chris@16 288 template<typename Key,typename Value,typename KeyFromValue>
Chris@16 289 struct key_value:
Chris@16 290 mpl::if_<
Chris@16 291 is_same<KeyFromValue,no_key_from_value>,
Chris@16 292 detail::regular_key_value<Key,Value>,
Chris@16 293 detail::optimized_key_value<Key,Value,KeyFromValue>
Chris@16 294 >::type
Chris@16 295 {};
Chris@16 296
Chris@16 297 } /* namespace flyweights */
Chris@16 298
Chris@16 299 } /* namespace boost */
Chris@16 300
Chris@16 301 #endif