source: NonGTP/Boost/boost/spirit/fusion/detail/config.hpp @ 857

Revision 857, 15.8 KB checked in by igarcia, 18 years ago (diff)
Line 
1/*=============================================================================
2    Copyright (c) 2001-2003 Joel de Guzman
3    Copyright (c) 2004 Peder Holt
4
5    Use, modification and distribution is subject to the Boost Software
6    License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
7    http://www.boost.org/LICENSE_1_0.txt)
8==============================================================================*/
9#if !defined(FUSION_DETAIL_CONFIG_HPP)
10#define FUSION_DETAIL_CONFIG_HPP
11
12#include <boost/config.hpp>
13#include <boost/detail/workaround.hpp>
14#include <boost/preprocessor/cat.hpp>
15#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
16#include <boost/mpl/bool.hpp>
17#endif
18
19#if     (defined(BOOST_MSVC) && (BOOST_MSVC < 1310))                            \
20    ||  (defined(__BORLANDC__) && (__BORLANDC__ <= 0x570))                      \
21    ||  (defined(__GNUC__) && (__GNUC__ < 3))                                   \
22    ||  (defined(__GNUC__) && (__GNUC__ == 3) && (__GNUC_MINOR__ < 1))
23#else
24# define FUSION_COMFORMING_COMPILER
25#endif
26
27///////////////////////////////////////////////////////////////////////////////
28//
29//  BOOST_NO_TEMPLATED_STREAMS macro. This ought to be in boost.config
30//
31///////////////////////////////////////////////////////////////////////////////
32#if defined __GNUC__ && __GNUC__ == 2 && __GNUC_MINOR__ <= 97
33#define BOOST_NO_TEMPLATED_STREAMS
34#endif
35
36///////////////////////////////////////////////////////////////////////////////
37//
38//  Before including MPL, we define these dummy template functions. Borland
39//  complains when a template class has the same name as a template function,
40//  regardless if they are in different namespaces. This is a workaround to
41//  this Borland quirk.
42//
43///////////////////////////////////////////////////////////////////////////////
44#if BOOST_WORKAROUND(__BORLANDC__, <= 0x551)
45namespace boost { namespace fusion { namespace borland_only {
46
47    template <typename T> void begin(T) {}
48    template <typename T> void end(T) {}
49    template <typename T> void next(T) {}
50    template <typename T> void prior(T) {}
51    template <typename T> void find(T) {}
52    template <typename T> void find_if(T) {}
53
54}}}
55#endif
56
57///////////////////////////////////////////////////////////////////////////////
58//
59//  MSVC, even with VC7.1 has problems with returning a default constructed
60//  value of a given type: return type(); This only happens on debug builds.
61//  It seems to be a return value optimization bug.
62//
63///////////////////////////////////////////////////////////////////////////////
64#if BOOST_WORKAROUND(BOOST_MSVC, <= 1301) && !defined(NDEBUG)
65# define FUSION_RETURN_DEFAULT_CONSTRUCTED type r=type(); return r
66#else
67# define FUSION_RETURN_DEFAULT_CONSTRUCTED return type()
68#endif
69
70///////////////////////////////////////////////////////////////////////////////
71//
72//  Borland does not like the T::value syntax. Instead, we use a metafunction
73//  get_value<T>::value. The explicit qualification (::boost::fusion::detail::)
74//  also makes Borland happy.
75//
76//  VC6/7 on the other hand chokes with ETI (early instantiation bug). So we
77//  forward the call to get_value<T>::value and fix the ETI bug there (see
78//  get_value below).
79//
80///////////////////////////////////////////////////////////////////////////////
81#if BOOST_WORKAROUND(__BORLANDC__, <= 0x551)                                    \
82    || BOOST_WORKAROUND(BOOST_MSVC, < 1300)
83namespace boost { namespace fusion { namespace detail
84{
85    template <typename T>
86    struct get_value
87    {
88        BOOST_STATIC_CONSTANT(int, value = T::value);
89    };
90
91#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
92
93    // VC6 ETI (early template instantiation) bug workaround.
94    template <>
95    struct get_value<int>
96    {
97        BOOST_STATIC_CONSTANT(int, value = 0);
98    };
99#endif
100}}}
101#endif
102
103#if BOOST_WORKAROUND(__BORLANDC__, <= 0x551)                                    \
104    || BOOST_WORKAROUND(BOOST_MSVC, < 1300)
105# define FUSION_GET_VALUE(T) ::boost::fusion::detail::get_value<T>::value
106#else
107# define FUSION_GET_VALUE(T) T::value
108#endif
109
110///////////////////////////////////////////////////////////////////////////////
111//
112//  Borland does not like returning a const reference from a tuple member.
113//  We do the cast explicitly.
114//
115///////////////////////////////////////////////////////////////////////////////
116#if BOOST_WORKAROUND(__BORLANDC__, <= 0x551)
117# define FUSION_RETURN_TUPLE_MEMBER(n)                                          \
118    typedef typename tuple_access_result<n, Tuple>::type type;                  \
119    return type(t.BOOST_PP_CAT(m, n))
120#else
121# define FUSION_RETURN_TUPLE_MEMBER(n)                                          \
122    return t.BOOST_PP_CAT(m, n)
123#endif
124
125///////////////////////////////////////////////////////////////////////////////
126//
127//  See get.hpp. In function get<N>(t), mpl::int_<N>* = 0 is a function
128//  parameter that defaults to 0. This is a hack to make VC6 happy, otherwise,
129//  VC6 will return the wrong result from a wrong index!
130//
131///////////////////////////////////////////////////////////////////////////////
132#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
133# define FUSION_GET_MSVC_WORKAROUND , mpl::int_<N>* = 0
134#else
135# define FUSION_GET_MSVC_WORKAROUND
136#endif
137
138///////////////////////////////////////////////////////////////////////////////
139//
140//  FUSION_MSVC_ETI_WRAPPER (VC6 and VC7)
141//
142//  VC6/VC7 chokes with ETI (early instantiation bug) with typename T::name.
143//  So, we forward the call to get_name<T>::type and fix the ETI bug.
144//
145///////////////////////////////////////////////////////////////////////////////
146
147// VC6 ETI (early template instantiation) bug workaround.
148#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
149#define FUSION_MSVC_ETI_WRAPPER(name)                                           \
150namespace boost { namespace fusion { namespace detail                           \
151{                                                                               \
152    template <typename T>                                                       \
153    struct BOOST_PP_CAT(get_, name)                                             \
154    {                                                                           \
155        typedef typename T::name type;                                          \
156    };                                                                          \
157                                                                                \
158    template <>                                                                 \
159    struct BOOST_PP_CAT(get_, name)<int>                                        \
160    {                                                                           \
161        typedef int type;                                                       \
162    };                                                                          \
163}}}
164#endif
165/*
166//  is_msvc_70_ETI_arg: Detect a VC7 ETI arg
167#if BOOST_WORKAROUND(BOOST_MSVC, == 1300)
168namespace boost { namespace fusion { namespace detail
169{
170    struct int_convertible_
171    {
172        int_convertible_(int);
173    };
174
175    template< typename T >
176    struct is_msvc_70_ETI_arg
177    {
178        typedef char (&no_tag)[1];
179        typedef char (&yes_tag)[2];
180
181        static no_tag test(...);
182        static yes_tag test(int_convertible_);
183        static T get();
184
185        BOOST_STATIC_CONSTANT(bool, value =
186              sizeof(test(get())) == sizeof(yes_tag)
187            );
188    };
189}}}
190#endif
191
192// VC7 ETI (early template instantiation) bug workaround.
193#if BOOST_WORKAROUND(BOOST_MSVC, == 1300)
194#define FUSION_MSVC_ETI_WRAPPER(name)                                           \
195namespace boost { namespace fusion { namespace detail                           \
196{                                                                               \
197    template <bool>                                                             \
198    struct BOOST_PP_CAT(get_impl_, name)                                        \
199    {                                                                           \
200        template <typename T>                                                   \
201        struct result                                                           \
202        {                                                                       \
203            typedef int type;                                                   \
204        };                                                                      \
205    };                                                                          \
206                                                                                \
207    struct BOOST_PP_CAT(get_impl_, name)<false>                                 \
208    {                                                                           \
209        template <typename T>                                                   \
210        struct result                                                           \
211        {                                                                       \
212            typedef typename T::name type;                                      \
213        };                                                                      \
214    };                                                                          \
215                                                                                \
216    template <typename T>                                                       \
217    struct BOOST_PP_CAT(get_, name)                                             \
218        : BOOST_PP_CAT(get_impl_, name)<is_msvc_70_ETI_arg<T>::value>           \
219            ::template result<T> {};                                            \
220}}}
221#endif
222*/
223///////////////////////////////////////////////////////////////////////////////
224//
225//  T::tag wrapper
226//
227///////////////////////////////////////////////////////////////////////////////
228#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
229FUSION_MSVC_ETI_WRAPPER(tag)
230# define FUSION_GET_TAG(T) ::boost::fusion::detail::get_tag<T>::type
231#else
232# define FUSION_GET_TAG(T) typename T::tag
233#endif
234
235///////////////////////////////////////////////////////////////////////////////
236//
237//  T::type wrapper
238//
239///////////////////////////////////////////////////////////////////////////////
240#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
241FUSION_MSVC_ETI_WRAPPER(type)
242# define FUSION_GET_TYPE(T) ::boost::fusion::detail::get_type<T>::type
243#else
244# define FUSION_GET_TYPE(T) typename T::type
245#endif
246
247///////////////////////////////////////////////////////////////////////////////
248//
249//  T::types wrapper
250//
251///////////////////////////////////////////////////////////////////////////////
252#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
253FUSION_MSVC_ETI_WRAPPER(types)
254# define FUSION_GET_TYPES(T) ::boost::fusion::detail::get_types<T>::type
255#else
256# define FUSION_GET_TYPES(T) typename T::types
257#endif
258
259///////////////////////////////////////////////////////////////////////////////
260//
261//  T::index wrapper
262//
263///////////////////////////////////////////////////////////////////////////////
264#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
265FUSION_MSVC_ETI_WRAPPER(index)
266# define FUSION_GET_INDEX(T) ::boost::fusion::detail::get_index<T>::type
267#else
268# define FUSION_GET_INDEX(T) typename T::index
269#endif
270
271///////////////////////////////////////////////////////////////////////////////
272//
273//  T::tuple wrapper
274//
275///////////////////////////////////////////////////////////////////////////////
276#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
277FUSION_MSVC_ETI_WRAPPER(tuple)
278# define FUSION_GET_TUPLE(T) ::boost::fusion::detail::get_tuple<T>::type
279#else
280# define FUSION_GET_TUPLE(T) typename T::tuple
281#endif
282
283///////////////////////////////////////////////////////////////////////////////
284//
285//  T::size wrapper
286//
287///////////////////////////////////////////////////////////////////////////////
288#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
289FUSION_MSVC_ETI_WRAPPER(size)
290# define FUSION_GET_SIZE(T) ::boost::fusion::detail::get_size<T>::type
291#else
292# define FUSION_GET_SIZE(T) typename T::size
293#endif
294
295///////////////////////////////////////////////////////////////////////////////
296//
297//  T::value_type wrapper
298//
299///////////////////////////////////////////////////////////////////////////////
300#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
301FUSION_MSVC_ETI_WRAPPER(value_type)
302# define FUSION_GET_VALUE_TYPE(T) ::boost::fusion::detail::get_value_type<T>::type
303#else
304# define FUSION_GET_VALUE_TYPE(T) typename T::value_type
305#endif
306
307#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
308
309namespace boost {namespace fusion { namespace aux {
310template< typename T >
311struct msvc_never_true
312{
313    enum { value = false };
314};
315}}} //namespace boost::fusion::aux
316
317#endif
318
319namespace boost {namespace fusion {
320#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
321
322namespace aux {
323    // msvc_apply
324#define AUX778076_MSVC_DTW_NAME msvc_apply1
325#define AUX778076_MSVC_DTW_ORIGINAL_NAME apply
326#define AUX778076_MSVC_DTW_ARITY 1
327#include "boost/mpl/aux_/msvc_dtw.hpp"
328
329#define AUX778076_MSVC_DTW_NAME msvc_apply2
330#define AUX778076_MSVC_DTW_ORIGINAL_NAME apply
331#define AUX778076_MSVC_DTW_ARITY 2
332#include "boost/mpl/aux_/msvc_dtw.hpp"
333
334} //namespace aux
335
336template<typename A,typename B>
337struct fusion_apply1
338{
339    typedef typename aux::msvc_apply1<A>::template result_<B>::type type;
340};
341
342template<typename A,typename B,typename C>
343struct fusion_apply2
344{
345    typedef typename aux::msvc_apply2<A>::template result_<B,C>::type type;
346};
347
348#else
349template<typename A,typename B>
350struct fusion_apply1
351{
352    typedef typename A::template apply<B>::type type;
353};
354template<typename A,typename B,typename C>
355struct fusion_apply2
356{
357    typedef typename A::template apply<B,C>::type type;
358};
359#endif
360}} //namespace boost::fusion
361
362namespace boost {namespace fusion {namespace detail {
363#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
364    template<typename T>
365    struct bool_base {};
366    template<>
367    struct bool_base<mpl::bool_<true> > : boost::mpl::bool_<true>{};
368    template<>
369    struct bool_base<mpl::bool_<false> > : boost::mpl::bool_<false>{};
370#else
371    template<typename T>
372    struct bool_base : T {};
373#endif
374}}}
375
376//VC 6 has serious problems with mpl::int_ in tuple_iterator_base.
377//It ICEs because operator int() const on mpl::int_ is inlined.
378//At the same time, another test using integral_c<T,N> ICEs because operator int() is not inlined.
379//Only solution seems to be to define a special msvc_fusion_int for VC 6 to be used in tuple_iterator_base
380#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
381namespace boost {namespace fusion {namespace detail{
382
383template<int N>
384struct msvc_fusion_int
385{
386    BOOST_STATIC_CONSTANT(int, value = N);
387    typedef msvc_fusion_int<N> type;
388    typedef int value_type;
389    typedef boost::mpl::integral_c_tag tag;
390
391    typedef msvc_fusion_int<value + 1> next;
392    typedef msvc_fusion_int<value - 1> prior;
393
394    operator int() const;
395};
396
397template<int N>
398msvc_fusion_int<N>::operator int() const
399{
400    return static_cast<int>(this->value);
401}
402
403}}}
404#define FUSION_INT(N) boost::fusion::detail::msvc_fusion_int<N>
405#else
406#define FUSION_INT(N) boost::mpl::int_<N>
407#endif
408
409
410
411///////////////////////////////////////////////////////////////////////////////
412//
413//   Borland is so flaky with const correctness of iterators. It's getting
414//   confused with tuple_iterator<N, T> where T is a const tuple. We cast
415//   what Borland thinks is a const reference to a true reference.
416//
417///////////////////////////////////////////////////////////////////////////////
418namespace boost { namespace fusion { namespace detail
419{
420#if BOOST_WORKAROUND(__BORLANDC__, <= 0x551)
421
422    template <typename T>
423    T& ref(T const& r)
424    {
425        return const_cast<T&>(r);
426    }
427
428#else
429
430    template <typename T>
431    T& ref(T& r)
432    {
433        return r;
434    }
435
436#endif
437
438}}}
439
440#endif
441
442
Note: See TracBrowser for help on using the repository browser.