]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | #include <boost/variant/detail/move.hpp> | |
24 | ||
25 | #if !defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE) | |
26 | # include <boost/mpl/aux_/value_wknd.hpp> | |
27 | # include <boost/mpl/int.hpp> | |
28 | # include <boost/mpl/iter_fold.hpp> | |
29 | # include <boost/mpl/next.hpp> | |
30 | # include <boost/mpl/deref.hpp> | |
31 | # include <boost/mpl/pair.hpp> | |
32 | # include <boost/mpl/protect.hpp> | |
33 | #else | |
34 | # include <boost/variant/variant_fwd.hpp> | |
35 | # include <boost/preprocessor/cat.hpp> | |
36 | # include <boost/preprocessor/enum.hpp> | |
37 | # include <boost/preprocessor/repeat.hpp> | |
38 | #endif | |
39 | ||
40 | namespace boost { | |
41 | namespace detail { namespace variant { | |
42 | ||
43 | /////////////////////////////////////////////////////////////////////////////// | |
44 | // (detail) support to simulate standard overload resolution rules | |
45 | // | |
46 | // The below initializers allows variant to follow standard overload | |
47 | // resolution rules over the specified set of bounded types. | |
48 | // | |
49 | // On compilers where using declarations in class templates can correctly | |
50 | // avoid name hiding, use an optimal solution based on the variant's typelist. | |
51 | // | |
52 | // Otherwise, use a preprocessor workaround based on knowledge of the fixed | |
53 | // size of the variant's psuedo-variadic template parameter list. | |
54 | // | |
55 | ||
56 | #if !defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE) | |
57 | ||
58 | // (detail) quoted metafunction make_initializer_node | |
59 | // | |
60 | // Exposes a pair whose first type is a node in the initializer hierarchy. | |
61 | // | |
62 | struct make_initializer_node | |
63 | { | |
64 | template <typename BaseIndexPair, typename Iterator> | |
65 | struct apply | |
66 | { | |
67 | private: // helpers, for metafunction result (below) | |
68 | ||
69 | typedef typename BaseIndexPair::first | |
70 | base; | |
71 | typedef typename BaseIndexPair::second | |
72 | index; | |
73 | ||
74 | class initializer_node | |
75 | : public base | |
76 | { | |
77 | private: // helpers, for static functions (below) | |
78 | ||
79 | typedef typename mpl::deref<Iterator>::type | |
80 | recursive_enabled_T; | |
81 | typedef typename unwrap_recursive<recursive_enabled_T>::type | |
82 | public_T; | |
83 | ||
84 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES | |
85 | typedef boost::is_reference<public_T> | |
86 | is_reference_content_t; | |
87 | ||
88 | typedef typename boost::mpl::if_<is_reference_content_t, public_T, const public_T& >::type | |
89 | param_T; | |
90 | ||
91 | template <class T> struct disable_overload{}; | |
92 | ||
93 | typedef typename boost::mpl::if_<is_reference_content_t, disable_overload<public_T>, public_T&& >::type | |
94 | param2_T; | |
95 | #else | |
96 | typedef typename call_traits<public_T>::param_type | |
97 | param_T; | |
98 | #endif | |
99 | ||
100 | public: // static functions | |
101 | ||
102 | using base::initialize; | |
103 | ||
104 | static int initialize(void* dest, param_T operand) | |
105 | { | |
106 | typedef typename boost::detail::make_reference_content< | |
107 | recursive_enabled_T | |
108 | >::type internal_T; | |
109 | ||
110 | new(dest) internal_T(operand); | |
111 | return BOOST_MPL_AUX_VALUE_WKND(index)::value; // which | |
112 | } | |
113 | ||
114 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES | |
115 | static int initialize(void* dest, param2_T operand) | |
116 | { | |
117 | // This assert must newer trigger, because all the reference contents are | |
118 | // handled by the initilize(void* dest, param_T operand) function above | |
119 | BOOST_ASSERT(!is_reference_content_t::value); | |
120 | ||
121 | typedef typename boost::mpl::if_<is_reference_content_t, param2_T, recursive_enabled_T>::type value_T; | |
122 | new(dest) value_T( boost::detail::variant::move(operand) ); | |
123 | return BOOST_MPL_AUX_VALUE_WKND(index)::value; // which | |
124 | } | |
125 | #endif | |
126 | }; | |
127 | ||
128 | friend class initializer_node; | |
129 | ||
130 | public: // metafunction result | |
131 | ||
132 | typedef mpl::pair< | |
133 | initializer_node | |
134 | , typename mpl::next< index >::type | |
135 | > type; | |
136 | ||
137 | }; | |
138 | }; | |
139 | ||
140 | // (detail) class initializer_root | |
141 | // | |
142 | // Every level of the initializer hierarchy must expose the name | |
143 | // "initialize," so initializer_root provides a dummy function: | |
144 | // | |
145 | class initializer_root | |
146 | { | |
147 | public: // static functions | |
148 | ||
149 | static void initialize(); | |
150 | ||
151 | }; | |
152 | ||
153 | #else // defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE) | |
154 | ||
155 | // Obsolete. Remove. | |
156 | #define BOOST_VARIANT_AUX_PP_INITIALIZER_TEMPLATE_PARAMS \ | |
157 | BOOST_VARIANT_ENUM_PARAMS(typename recursive_enabled_T) \ | |
158 | /**/ | |
159 | ||
160 | // Obsolete. Remove. | |
161 | #define BOOST_VARIANT_AUX_PP_INITIALIZER_DEFINE_PARAM_T(N) \ | |
162 | typedef typename unwrap_recursive< \ | |
163 | BOOST_PP_CAT(recursive_enabled_T,N) \ | |
164 | >::type BOOST_PP_CAT(public_T,N); \ | |
165 | typedef typename call_traits< \ | |
166 | BOOST_PP_CAT(public_T,N) \ | |
167 | >::param_type BOOST_PP_CAT(param_T,N); \ | |
168 | /**/ | |
169 | ||
170 | template < BOOST_VARIANT_ENUM_PARAMS(typename recursive_enabled_T) > | |
171 | struct preprocessor_list_initializer | |
172 | { | |
173 | public: // static functions | |
174 | ||
175 | #define BOOST_VARIANT_AUX_PP_INITIALIZE_FUNCTION(z,N,_) \ | |
176 | typedef typename unwrap_recursive< \ | |
177 | BOOST_PP_CAT(recursive_enabled_T,N) \ | |
178 | >::type BOOST_PP_CAT(public_T,N); \ | |
179 | typedef typename call_traits< \ | |
180 | BOOST_PP_CAT(public_T,N) \ | |
181 | >::param_type BOOST_PP_CAT(param_T,N); \ | |
182 | static int initialize( \ | |
183 | void* dest \ | |
184 | , BOOST_PP_CAT(param_T,N) operand \ | |
185 | ) \ | |
186 | { \ | |
187 | typedef typename boost::detail::make_reference_content< \ | |
188 | BOOST_PP_CAT(recursive_enabled_T,N) \ | |
189 | >::type internal_T; \ | |
190 | \ | |
191 | new(dest) internal_T(operand); \ | |
192 | return (N); /*which*/ \ | |
193 | } \ | |
194 | /**/ | |
195 | ||
196 | BOOST_PP_REPEAT( | |
197 | BOOST_VARIANT_LIMIT_TYPES | |
198 | , BOOST_VARIANT_AUX_PP_INITIALIZE_FUNCTION | |
199 | , _ | |
200 | ) | |
201 | ||
202 | #undef BOOST_VARIANT_AUX_PP_INITIALIZE_FUNCTION | |
203 | ||
204 | }; | |
205 | ||
206 | #endif // BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE workaround | |
207 | ||
208 | }} // namespace detail::variant | |
209 | } // namespace boost | |
210 | ||
211 | /////////////////////////////////////////////////////////////////////////////// | |
212 | // macro BOOST_VARIANT_AUX_INITIALIZER_T | |
213 | // | |
214 | // Given both the variant's typelist and a basename for forming the list of | |
215 | // bounded types (i.e., T becomes T1, T2, etc.), exposes the initializer | |
216 | // most appropriate to the current compiler. | |
217 | // | |
218 | ||
219 | #if !defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE) | |
220 | ||
221 | #define BOOST_VARIANT_AUX_INITIALIZER_T( mpl_seq, typename_base ) \ | |
222 | ::boost::mpl::iter_fold< \ | |
223 | mpl_seq \ | |
224 | , ::boost::mpl::pair< \ | |
225 | ::boost::detail::variant::initializer_root \ | |
226 | , ::boost::mpl::int_<0> \ | |
227 | > \ | |
228 | , ::boost::mpl::protect< \ | |
229 | ::boost::detail::variant::make_initializer_node \ | |
230 | > \ | |
231 | >::type::first \ | |
232 | /**/ | |
233 | ||
234 | #else // defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE) | |
235 | ||
236 | // Obsolete. Remove. | |
237 | #define BOOST_VARIANT_AUX_PP_INITIALIZER_TEMPLATE_ARGS(typename_base) \ | |
238 | BOOST_VARIANT_ENUM_PARAMS(typename_base) \ | |
239 | /**/ | |
240 | ||
241 | #define BOOST_VARIANT_AUX_INITIALIZER_T( mpl_seq, typename_base ) \ | |
242 | ::boost::detail::variant::preprocessor_list_initializer< \ | |
243 | BOOST_VARIANT_ENUM_PARAMS(typename_base) \ | |
244 | > \ | |
245 | /**/ | |
246 | ||
247 | #endif // BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE workaround | |
248 | ||
249 | #endif // BOOST_VARIANT_DETAIL_INITIALIZER_HPP |