|
1 //----------------------------------------------------------------------------- |
|
2 // boost variant/detail/initializer.hpp header file |
|
3 // See http://www.boost.org for updates, documentation, and revision history. |
|
4 //----------------------------------------------------------------------------- |
|
5 // |
|
6 // Copyright (c) 2002-2003 |
|
7 // Eric Friedman, Itay Maman |
|
8 // |
|
9 // Distributed under the Boost Software License, Version 1.0. (See |
|
10 // accompanying file LICENSE_1_0.txt or copy at |
|
11 // http://www.boost.org/LICENSE_1_0.txt) |
|
12 |
|
13 #ifndef BOOST_VARIANT_DETAIL_INITIALIZER_HPP |
|
14 #define BOOST_VARIANT_DETAIL_INITIALIZER_HPP |
|
15 |
|
16 #include <new> // for placement new |
|
17 |
|
18 #include "boost/config.hpp" |
|
19 |
|
20 #include "boost/call_traits.hpp" |
|
21 #include "boost/detail/reference_content.hpp" |
|
22 #include "boost/variant/recursive_wrapper_fwd.hpp" |
|
23 |
|
24 #if !defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE) |
|
25 # include "boost/mpl/aux_/value_wknd.hpp" |
|
26 # include "boost/mpl/int.hpp" |
|
27 # include "boost/mpl/iter_fold.hpp" |
|
28 # include "boost/mpl/next.hpp" |
|
29 # include "boost/mpl/deref.hpp" |
|
30 # include "boost/mpl/pair.hpp" |
|
31 # include "boost/mpl/protect.hpp" |
|
32 #else |
|
33 # include "boost/variant/variant_fwd.hpp" |
|
34 # include "boost/preprocessor/cat.hpp" |
|
35 # include "boost/preprocessor/enum.hpp" |
|
36 # include "boost/preprocessor/repeat.hpp" |
|
37 #endif |
|
38 |
|
39 namespace boost { |
|
40 namespace detail { namespace variant { |
|
41 |
|
42 /////////////////////////////////////////////////////////////////////////////// |
|
43 // (detail) support to simulate standard overload resolution rules |
|
44 // |
|
45 // The below initializers allows variant to follow standard overload |
|
46 // resolution rules over the specified set of bounded types. |
|
47 // |
|
48 // On compilers where using declarations in class templates can correctly |
|
49 // avoid name hiding, use an optimal solution based on the variant's typelist. |
|
50 // |
|
51 // Otherwise, use a preprocessor workaround based on knowledge of the fixed |
|
52 // size of the variant's psuedo-variadic template parameter list. |
|
53 // |
|
54 |
|
55 #if !defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE) |
|
56 |
|
57 // (detail) quoted metafunction make_initializer_node |
|
58 // |
|
59 // Exposes a pair whose first type is a node in the initializer hierarchy. |
|
60 // |
|
61 struct make_initializer_node |
|
62 { |
|
63 template <typename BaseIndexPair, typename Iterator> |
|
64 struct apply |
|
65 { |
|
66 private: // helpers, for metafunction result (below) |
|
67 |
|
68 typedef typename BaseIndexPair::first |
|
69 base; |
|
70 typedef typename BaseIndexPair::second |
|
71 index; |
|
72 |
|
73 class initializer_node |
|
74 : public base |
|
75 { |
|
76 private: // helpers, for static functions (below) |
|
77 |
|
78 typedef typename mpl::deref<Iterator>::type |
|
79 recursive_enabled_T; |
|
80 typedef typename unwrap_recursive<recursive_enabled_T>::type |
|
81 public_T; |
|
82 typedef typename call_traits<public_T>::param_type |
|
83 param_T; |
|
84 |
|
85 public: // static functions |
|
86 |
|
87 using base::initialize; |
|
88 |
|
89 static int initialize(void* dest, param_T operand) |
|
90 { |
|
91 typedef typename boost::detail::make_reference_content< |
|
92 recursive_enabled_T |
|
93 >::type internal_T; |
|
94 |
|
95 new(dest) internal_T(operand); |
|
96 return BOOST_MPL_AUX_VALUE_WKND(index)::value; // which |
|
97 } |
|
98 |
|
99 }; |
|
100 |
|
101 friend class initializer_node; |
|
102 |
|
103 public: // metafunction result |
|
104 |
|
105 typedef mpl::pair< |
|
106 initializer_node |
|
107 , typename mpl::next< index >::type |
|
108 > type; |
|
109 |
|
110 }; |
|
111 }; |
|
112 |
|
113 // (detail) class initializer_root |
|
114 // |
|
115 // Every level of the initializer hierarchy must expose the name |
|
116 // "initialize," so initializer_root provides a dummy function: |
|
117 // |
|
118 class initializer_root |
|
119 { |
|
120 public: // static functions |
|
121 |
|
122 static void initialize(); |
|
123 |
|
124 }; |
|
125 |
|
126 #else // defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE) |
|
127 |
|
128 # if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) |
|
129 |
|
130 #define BOOST_VARIANT_AUX_PP_INITIALIZER_TEMPLATE_PARAMS \ |
|
131 BOOST_VARIANT_ENUM_PARAMS(typename recursive_enabled_T) \ |
|
132 /**/ |
|
133 |
|
134 #define BOOST_VARIANT_AUX_PP_INITIALIZER_DEFINE_PARAM_T(N) \ |
|
135 typedef typename unwrap_recursive< \ |
|
136 BOOST_PP_CAT(recursive_enabled_T,N) \ |
|
137 >::type BOOST_PP_CAT(public_T,N); \ |
|
138 typedef typename call_traits< \ |
|
139 BOOST_PP_CAT(public_T,N) \ |
|
140 >::param_type BOOST_PP_CAT(param_T,N); \ |
|
141 /**/ |
|
142 |
|
143 # else // MSVC7 and below |
|
144 |
|
145 #define BOOST_VARIANT_AUX_PP_INITIALIZER_TEMPLATE_PARAMS \ |
|
146 BOOST_VARIANT_ENUM_PARAMS(typename recursive_enabled_T) \ |
|
147 , BOOST_VARIANT_ENUM_PARAMS(typename param_T) \ |
|
148 /**/ |
|
149 |
|
150 #define BOOST_VARIANT_AUX_PP_INITIALIZER_DEFINE_PARAM_T(N) \ |
|
151 /**/ |
|
152 |
|
153 # endif // MSVC7 and below workaround |
|
154 |
|
155 template < BOOST_VARIANT_AUX_PP_INITIALIZER_TEMPLATE_PARAMS > |
|
156 struct preprocessor_list_initializer |
|
157 { |
|
158 public: // static functions |
|
159 |
|
160 #define BOOST_VARIANT_AUX_PP_INITIALIZE_FUNCTION(z,N,_) \ |
|
161 BOOST_VARIANT_AUX_PP_INITIALIZER_DEFINE_PARAM_T(N) \ |
|
162 static int initialize( \ |
|
163 void* dest \ |
|
164 , BOOST_PP_CAT(param_T,N) operand \ |
|
165 ) \ |
|
166 { \ |
|
167 typedef typename boost::detail::make_reference_content< \ |
|
168 BOOST_PP_CAT(recursive_enabled_T,N) \ |
|
169 >::type internal_T; \ |
|
170 \ |
|
171 new(dest) internal_T(operand); \ |
|
172 return (N); /*which*/ \ |
|
173 } \ |
|
174 /**/ |
|
175 |
|
176 BOOST_PP_REPEAT( |
|
177 BOOST_VARIANT_LIMIT_TYPES |
|
178 , BOOST_VARIANT_AUX_PP_INITIALIZE_FUNCTION |
|
179 , _ |
|
180 ) |
|
181 |
|
182 #undef BOOST_VARIANT_AUX_PP_INITIALIZE_FUNCTION |
|
183 |
|
184 }; |
|
185 |
|
186 # if defined(BOOST_MPL_CFG_MSVC_60_ETI_BUG) |
|
187 |
|
188 #if !defined(BOOST_VARIANT_AUX_ECHO) |
|
189 # define BOOST_VARIANT_AUX_ECHO(z,N,token) token |
|
190 #endif |
|
191 |
|
192 template <> |
|
193 struct preprocessor_list_initializer< |
|
194 BOOST_PP_ENUM(BOOST_VARIANT_LIMIT_TYPES, BOOST_VARIANT_AUX_ECHO, int) |
|
195 , BOOST_PP_ENUM(BOOST_VARIANT_LIMIT_TYPES, BOOST_VARIANT_AUX_ECHO, const int) |
|
196 > |
|
197 { |
|
198 }; |
|
199 |
|
200 # endif // BOOST_MPL_CFG_MSVC_60_ETI_BUG workaround |
|
201 |
|
202 #endif // BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE workaround |
|
203 |
|
204 }} // namespace detail::variant |
|
205 } // namespace boost |
|
206 |
|
207 /////////////////////////////////////////////////////////////////////////////// |
|
208 // macro BOOST_VARIANT_AUX_INITIALIZER_T |
|
209 // |
|
210 // Given both the variant's typelist and a basename for forming the list of |
|
211 // bounded types (i.e., T becomes T1, T2, etc.), exposes the initializer |
|
212 // most appropriate to the current compiler. |
|
213 // |
|
214 |
|
215 #if !defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE) |
|
216 |
|
217 #define BOOST_VARIANT_AUX_INITIALIZER_T( mpl_seq, typename_base ) \ |
|
218 ::boost::mpl::iter_fold< \ |
|
219 mpl_seq \ |
|
220 , ::boost::mpl::pair< \ |
|
221 ::boost::detail::variant::initializer_root \ |
|
222 , ::boost::mpl::int_<0> \ |
|
223 > \ |
|
224 , ::boost::mpl::protect< \ |
|
225 ::boost::detail::variant::make_initializer_node \ |
|
226 > \ |
|
227 >::type::first \ |
|
228 /**/ |
|
229 |
|
230 #else // defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE) |
|
231 |
|
232 # if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) |
|
233 |
|
234 #define BOOST_VARIANT_AUX_PP_INITIALIZER_TEMPLATE_ARGS(typename_base) \ |
|
235 BOOST_VARIANT_ENUM_PARAMS(typename_base) \ |
|
236 /**/ |
|
237 |
|
238 # else // MSVC7 and below |
|
239 |
|
240 #define BOOST_VARIANT_AUX_PP_INITIALIZER_ENUM_PARAM_TYPE(z,N,T) \ |
|
241 ::boost::call_traits< \ |
|
242 ::boost::unwrap_recursive<BOOST_PP_CAT(T,N)>::type \ |
|
243 >::param_type \ |
|
244 /**/ |
|
245 |
|
246 #define BOOST_VARIANT_AUX_PP_INITIALIZER_TEMPLATE_ARGS(typename_base) \ |
|
247 BOOST_VARIANT_ENUM_PARAMS(typename_base) \ |
|
248 , BOOST_PP_ENUM( \ |
|
249 BOOST_VARIANT_LIMIT_TYPES \ |
|
250 , BOOST_VARIANT_AUX_PP_INITIALIZER_ENUM_PARAM_TYPE \ |
|
251 , typename_base \ |
|
252 ) \ |
|
253 /**/ |
|
254 |
|
255 # endif // MSVC7 workaround |
|
256 |
|
257 #define BOOST_VARIANT_AUX_INITIALIZER_T( mpl_seq, typename_base ) \ |
|
258 ::boost::detail::variant::preprocessor_list_initializer< \ |
|
259 BOOST_VARIANT_AUX_PP_INITIALIZER_TEMPLATE_ARGS(typename_base) \ |
|
260 > \ |
|
261 /**/ |
|
262 |
|
263 #endif // BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE workaround |
|
264 |
|
265 #endif // BOOST_VARIANT_DETAIL_INITIALIZER_HPP |