Pack required boost code together.
[xy_vsfilter.git] / src / thirdparty / boost_1_47_0 / boost / flyweight / key_value.hpp
blobdd36236167ca7c61c9c500aa96996066dde27961
1 /* Copyright 2006-2008 Joaquin M Lopez Munoz.
2 * Distributed under the Boost Software License, Version 1.0.
3 * (See accompanying file LICENSE_1_0.txt or copy at
4 * http://www.boost.org/LICENSE_1_0.txt)
6 * See http://www.boost.org/libs/flyweight for library home page.
7 */
9 #ifndef BOOST_FLYWEIGHT_KEY_VALUE_HPP
10 #define BOOST_FLYWEIGHT_KEY_VALUE_HPP
12 #if defined(_MSC_VER)&&(_MSC_VER>=1200)
13 #pragma once
14 #endif
16 #include <boost/flyweight/detail/value_tag.hpp>
17 #include <boost/flyweight/key_value_fwd.hpp>
18 #include <boost/mpl/assert.hpp>
19 #include <boost/preprocessor/repetition/enum_params.hpp>
20 #include <boost/type_traits/aligned_storage.hpp>
21 #include <boost/type_traits/alignment_of.hpp>
22 #include <boost/type_traits/is_same.hpp>
23 #include <new>
25 /* key-value policy: flywewight lookup is based on Key, which also serves
26 * to construct Value only when needed (new factory entry). key_value is
27 * used to avoid the construction of temporary values when such construction
28 * is expensive.
29 * Optionally, KeyFromValue extracts the key from a value, which
30 * is needed in expressions like this:
32 * typedef flyweight<key_value<Key,Value> > fw_t;
33 * fw_t fw;
34 * Value v;
35 * fw=v; // no key explicitly given
37 * If no KeyFromValue is provided, this latter expression fails to compile.
40 namespace boost{
42 namespace flyweights{
44 namespace detail{
46 template<typename Key,typename Value,typename KeyFromValue>
47 struct optimized_key_value:value_marker
49 typedef Key key_type;
50 typedef Value value_type;
52 class rep_type
54 public:
55 /* template ctors */
57 #define BOOST_FLYWEIGHT_PERFECT_FWD_NAME explicit rep_type
58 #define BOOST_FLYWEIGHT_PERFECT_FWD_BODY(n) \
59 :value_ptr(0) \
60 { \
61 new(spc_ptr())key_type(BOOST_PP_ENUM_PARAMS(n,t)); \
63 #include <boost/flyweight/detail/perfect_fwd.hpp>
65 rep_type(const value_type& x):value_ptr(&x){}
67 rep_type(const rep_type& x):value_ptr(x.value_ptr)
69 if(!x.value_ptr)new(key_ptr())key_type(*x.key_ptr());
72 ~rep_type()
74 if(!value_ptr) key_ptr()->~key_type();
75 else if(value_cted())value_ptr->~value_type();
78 operator const key_type&()const
80 if(value_ptr)return key_from_value(*value_ptr);
81 else return *key_ptr();
84 operator const value_type&()const
86 /* This is always called after construct_value() or copy_value(),
87 * so we access spc directly rather than through value_ptr to
88 * save us an indirection.
91 return *static_cast<value_type*>(spc_ptr());
94 private:
95 friend struct optimized_key_value;
97 void* spc_ptr()const{return static_cast<void*>(&spc);}
98 bool value_cted()const{return value_ptr==spc_ptr();}
100 key_type* key_ptr()const
102 return static_cast<key_type*>(static_cast<void*>(&spc));
105 static const key_type& key_from_value(const value_type& x)
107 KeyFromValue k;
108 return k(x);
111 void construct_value()const
113 if(!value_cted()){
114 /* value_ptr must be ==0, oherwise copy_value would have been called */
116 key_type k(*key_ptr());
117 key_ptr()->~key_type();
118 value_ptr= /* guarantees key won't be re-dted at ~rep_type if the */
119 static_cast<value_type*>(spc_ptr())+1; /* next statement throws */
120 value_ptr=new(spc_ptr())value_type(k);
124 void copy_value()const
126 if(!value_cted())value_ptr=new(spc_ptr())value_type(*value_ptr);
129 mutable typename boost::aligned_storage<
130 (sizeof(key_type)>sizeof(value_type))?
131 sizeof(key_type):sizeof(value_type),
132 (boost::alignment_of<key_type>::value >
133 boost::alignment_of<value_type>::value)?
134 boost::alignment_of<key_type>::value:
135 boost::alignment_of<value_type>::value
136 >::type spc;
137 mutable const value_type* value_ptr;
140 static void construct_value(const rep_type& r)
142 r.construct_value();
145 static void copy_value(const rep_type& r)
147 r.copy_value();
151 template<typename Key,typename Value>
152 struct regular_key_value:value_marker
154 typedef Key key_type;
155 typedef Value value_type;
157 class rep_type
159 public:
160 /* template ctors */
162 #define BOOST_FLYWEIGHT_PERFECT_FWD_NAME explicit rep_type
163 #define BOOST_FLYWEIGHT_PERFECT_FWD_BODY(n) \
164 :key(BOOST_PP_ENUM_PARAMS(n,t)),value_ptr(0){}
165 #include <boost/flyweight/detail/perfect_fwd.hpp>
167 rep_type(const value_type& x):key(no_key_from_value_failure()){}
169 rep_type(const rep_type& x):key(x.key),value_ptr(0){}
171 ~rep_type()
173 if(value_ptr)value_ptr->~value_type();
176 operator const key_type&()const{return key;}
178 operator const value_type&()const
180 /* This is always called after construct_value(),so we access spc
181 * directly rather than through value_ptr to save us an indirection.
184 return *static_cast<value_type*>(spc_ptr());
187 private:
188 friend struct regular_key_value;
190 void* spc_ptr()const{return static_cast<void*>(&spc);}
192 struct no_key_from_value_failure
194 BOOST_MPL_ASSERT_MSG(
195 false,
196 NO_KEY_FROM_VALUE_CONVERSION_PROVIDED,
197 (key_type,value_type));
199 operator const key_type&()const;
202 void construct_value()const
204 if(!value_ptr)value_ptr=new(spc_ptr())value_type(key);
207 key_type key;
208 mutable typename boost::aligned_storage<
209 sizeof(value_type),
210 boost::alignment_of<value_type>::value
211 >::type spc;
212 mutable const value_type* value_ptr;
215 static void construct_value(const rep_type& r)
217 r.construct_value();
220 static void copy_value(const rep_type&){}
223 } /* namespace flyweights::detail */
225 template<typename Key,typename Value,typename KeyFromValue>
226 struct key_value:
227 mpl::if_<
228 is_same<KeyFromValue,no_key_from_value>,
229 detail::regular_key_value<Key,Value>,
230 detail::optimized_key_value<Key,Value,KeyFromValue>
231 >::type
234 } /* namespace flyweights */
236 } /* namespace boost */
238 #endif