source: NonGTP/Boost/boost/variant/detail/initializer.hpp @ 857

Revision 857, 8.2 KB checked in by igarcia, 19 years ago (diff)
RevLine 
[857]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
39namespace boost {
40namespace 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//
61struct 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//
118class initializer_root
119{
120public: // 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
155template < BOOST_VARIANT_AUX_PP_INITIALIZER_TEMPLATE_PARAMS >
156struct preprocessor_list_initializer
157{
158public: // 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
192template <>
193struct 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
Note: See TracBrowser for help on using the repository browser.