summaryrefslogtreecommitdiffstats
blob: b14d6c8f8bc841b5c1a775f9350aa83706430796 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
//-----------------------------------------------------------------------------
// boost variant/detail/initializer.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2002-2003
// Eric Friedman, Itay Maman
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

#ifndef BOOST_VARIANT_DETAIL_INITIALIZER_HPP
#define BOOST_VARIANT_DETAIL_INITIALIZER_HPP

#include <new> // for placement new

#include "boost/config.hpp"

#include "boost/call_traits.hpp"
#include "boost/detail/reference_content.hpp"
#include "boost/variant/recursive_wrapper_fwd.hpp"

#if !defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE)
#   include "boost/mpl/aux_/value_wknd.hpp"
#   include "boost/mpl/int.hpp"
#   include "boost/mpl/iter_fold.hpp"
#   include "boost/mpl/next.hpp"
#   include "boost/mpl/deref.hpp"
#   include "boost/mpl/pair.hpp"
#   include "boost/mpl/protect.hpp"
#else
#   include "boost/variant/variant_fwd.hpp"
#   include "boost/preprocessor/cat.hpp"
#   include "boost/preprocessor/enum.hpp"
#   include "boost/preprocessor/repeat.hpp"
#endif

namespace boost {
namespace detail { namespace variant {

///////////////////////////////////////////////////////////////////////////////
// (detail) support to simulate standard overload resolution rules
//
// The below initializers allows variant to follow standard overload
// resolution rules over the specified set of bounded types.
//
// On compilers where using declarations in class templates can correctly
// avoid name hiding, use an optimal solution based on the variant's typelist.
//
// Otherwise, use a preprocessor workaround based on knowledge of the fixed
// size of the variant's psuedo-variadic template parameter list.
//

#if !defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE)

// (detail) quoted metafunction make_initializer_node
//
// Exposes a pair whose first type is a node in the initializer hierarchy.
//
struct make_initializer_node
{
    template <typename BaseIndexPair, typename Iterator>
    struct apply
    {
    private: // helpers, for metafunction result (below)

        typedef typename BaseIndexPair::first
            base;
        typedef typename BaseIndexPair::second
            index;

        class initializer_node
            : public base
        {
        private: // helpers, for static functions (below)

            typedef typename mpl::deref<Iterator>::type
                recursive_enabled_T;
            typedef typename unwrap_recursive<recursive_enabled_T>::type
                public_T;
            typedef typename call_traits<public_T>::param_type
                param_T;

        public: // static functions

            using base::initialize;

            static int initialize(void* dest, param_T operand)
            {
                typedef typename boost::detail::make_reference_content<
                      recursive_enabled_T
                    >::type internal_T;

                new(dest) internal_T(operand);
                return BOOST_MPL_AUX_VALUE_WKND(index)::value; // which
            }

        };

        friend class initializer_node;

    public: // metafunction result

        typedef mpl::pair<
              initializer_node
            , typename mpl::next< index >::type
            > type;

    };
};

// (detail) class initializer_root
//
// Every level of the initializer hierarchy must expose the name
// "initialize," so initializer_root provides a dummy function:
//
class initializer_root
{
public: // static functions

    static void initialize();

};

#else // defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE)

#   if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) 

    #define BOOST_VARIANT_AUX_PP_INITIALIZER_TEMPLATE_PARAMS \
          BOOST_VARIANT_ENUM_PARAMS(typename recursive_enabled_T) \
    /**/

    #define BOOST_VARIANT_AUX_PP_INITIALIZER_DEFINE_PARAM_T(N) \
        typedef typename unwrap_recursive< \
              BOOST_PP_CAT(recursive_enabled_T,N) \
            >::type BOOST_PP_CAT(public_T,N); \
        typedef typename call_traits< \
              BOOST_PP_CAT(public_T,N) \
            >::param_type BOOST_PP_CAT(param_T,N); \
    /**/

#   else // MSVC7 and below

    #define BOOST_VARIANT_AUX_PP_INITIALIZER_TEMPLATE_PARAMS \
          BOOST_VARIANT_ENUM_PARAMS(typename recursive_enabled_T) \
        , BOOST_VARIANT_ENUM_PARAMS(typename param_T) \
    /**/

    #define BOOST_VARIANT_AUX_PP_INITIALIZER_DEFINE_PARAM_T(N) \
    /**/

#   endif // MSVC7 and below workaround

template < BOOST_VARIANT_AUX_PP_INITIALIZER_TEMPLATE_PARAMS >
struct preprocessor_list_initializer
{
public: // static functions

    #define BOOST_VARIANT_AUX_PP_INITIALIZE_FUNCTION(z,N,_) \
        BOOST_VARIANT_AUX_PP_INITIALIZER_DEFINE_PARAM_T(N) \
        static int initialize( \
              void* dest \
            , BOOST_PP_CAT(param_T,N) operand \
            ) \
        { \
            typedef typename boost::detail::make_reference_content< \
                  BOOST_PP_CAT(recursive_enabled_T,N) \
                >::type internal_T; \
            \
            new(dest) internal_T(operand); \
            return (N); /*which*/ \
        } \
        /**/

    BOOST_PP_REPEAT(
          BOOST_VARIANT_LIMIT_TYPES
        , BOOST_VARIANT_AUX_PP_INITIALIZE_FUNCTION
        , _
        )

    #undef BOOST_VARIANT_AUX_PP_INITIALIZE_FUNCTION

};

#   if defined(BOOST_MPL_CFG_MSVC_60_ETI_BUG)

#if !defined(BOOST_VARIANT_AUX_ECHO)
#   define BOOST_VARIANT_AUX_ECHO(z,N,token) token
#endif

template <>
struct preprocessor_list_initializer<
      BOOST_PP_ENUM(BOOST_VARIANT_LIMIT_TYPES, BOOST_VARIANT_AUX_ECHO, int)
    , BOOST_PP_ENUM(BOOST_VARIANT_LIMIT_TYPES, BOOST_VARIANT_AUX_ECHO, const int)
    >
{
};

#   endif // BOOST_MPL_CFG_MSVC_60_ETI_BUG workaround

#endif // BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE workaround

}} // namespace detail::variant
} // namespace boost

///////////////////////////////////////////////////////////////////////////////
// macro BOOST_VARIANT_AUX_INITIALIZER_T
//
// Given both the variant's typelist and a basename for forming the list of
// bounded types (i.e., T becomes T1, T2, etc.), exposes the initializer
// most appropriate to the current compiler.
//

#if !defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE)

#define BOOST_VARIANT_AUX_INITIALIZER_T( mpl_seq, typename_base ) \
    ::boost::mpl::iter_fold< \
          mpl_seq \
        , ::boost::mpl::pair< \
              ::boost::detail::variant::initializer_root \
            , ::boost::mpl::int_<0> \
            > \
        , ::boost::mpl::protect< \
              ::boost::detail::variant::make_initializer_node \
            > \
        >::type::first \
    /**/

#else // defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE)

#   if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)

    #define BOOST_VARIANT_AUX_PP_INITIALIZER_TEMPLATE_ARGS(typename_base) \
          BOOST_VARIANT_ENUM_PARAMS(typename_base) \
        /**/

#   else // MSVC7 and below

    #define BOOST_VARIANT_AUX_PP_INITIALIZER_ENUM_PARAM_TYPE(z,N,T) \
        ::boost::call_traits< \
              ::boost::unwrap_recursive<BOOST_PP_CAT(T,N)>::type \
            >::param_type \
        /**/

    #define BOOST_VARIANT_AUX_PP_INITIALIZER_TEMPLATE_ARGS(typename_base) \
          BOOST_VARIANT_ENUM_PARAMS(typename_base) \
        , BOOST_PP_ENUM( \
              BOOST_VARIANT_LIMIT_TYPES \
            , BOOST_VARIANT_AUX_PP_INITIALIZER_ENUM_PARAM_TYPE \
            , typename_base \
            ) \
        /**/

#   endif // MSVC7 workaround

#define BOOST_VARIANT_AUX_INITIALIZER_T( mpl_seq, typename_base ) \
    ::boost::detail::variant::preprocessor_list_initializer< \
          BOOST_VARIANT_AUX_PP_INITIALIZER_TEMPLATE_ARGS(typename_base) \
        > \
    /**/

#endif // BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE workaround

#endif // BOOST_VARIANT_DETAIL_INITIALIZER_HPP