Chris@16
|
1 // Copyright David Abrahams 2004. Use, modification and distribution is
|
Chris@16
|
2 // subject to the Boost Software License, Version 1.0. (See accompanying
|
Chris@16
|
3 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
4 #ifndef IS_INCREMENTABLE_DWA200415_HPP
|
Chris@16
|
5 # define IS_INCREMENTABLE_DWA200415_HPP
|
Chris@16
|
6
|
Chris@16
|
7 # include <boost/type_traits/detail/template_arity_spec.hpp>
|
Chris@16
|
8 # include <boost/type_traits/remove_cv.hpp>
|
Chris@16
|
9 # include <boost/mpl/aux_/lambda_support.hpp>
|
Chris@16
|
10 # include <boost/mpl/bool.hpp>
|
Chris@16
|
11 # include <boost/detail/workaround.hpp>
|
Chris@16
|
12
|
Chris@16
|
13 // Must be the last include
|
Chris@16
|
14 # include <boost/type_traits/detail/bool_trait_def.hpp>
|
Chris@16
|
15
|
Chris@16
|
16 namespace boost { namespace detail {
|
Chris@16
|
17
|
Chris@16
|
18 // is_incrementable<T> metafunction
|
Chris@16
|
19 //
|
Chris@16
|
20 // Requires: Given x of type T&, if the expression ++x is well-formed
|
Chris@16
|
21 // it must have complete type; otherwise, it must neither be ambiguous
|
Chris@16
|
22 // nor violate access.
|
Chris@16
|
23
|
Chris@16
|
24 // This namespace ensures that ADL doesn't mess things up.
|
Chris@16
|
25 namespace is_incrementable_
|
Chris@16
|
26 {
|
Chris@16
|
27 // a type returned from operator++ when no increment is found in the
|
Chris@16
|
28 // type's own namespace
|
Chris@16
|
29 struct tag {};
|
Chris@16
|
30
|
Chris@16
|
31 // any soaks up implicit conversions and makes the following
|
Chris@16
|
32 // operator++ less-preferred than any other such operator that
|
Chris@16
|
33 // might be found via ADL.
|
Chris@16
|
34 struct any { template <class T> any(T const&); };
|
Chris@16
|
35
|
Chris@16
|
36 // This is a last-resort operator++ for when none other is found
|
Chris@16
|
37 # if BOOST_WORKAROUND(__GNUC__, == 4) && __GNUC_MINOR__ == 0 && __GNUC_PATCHLEVEL__ == 2
|
Chris@16
|
38
|
Chris@16
|
39 }
|
Chris@16
|
40
|
Chris@16
|
41 namespace is_incrementable_2
|
Chris@16
|
42 {
|
Chris@16
|
43 is_incrementable_::tag operator++(is_incrementable_::any const&);
|
Chris@16
|
44 is_incrementable_::tag operator++(is_incrementable_::any const&,int);
|
Chris@16
|
45 }
|
Chris@16
|
46 using namespace is_incrementable_2;
|
Chris@16
|
47
|
Chris@16
|
48 namespace is_incrementable_
|
Chris@16
|
49 {
|
Chris@16
|
50
|
Chris@16
|
51 # else
|
Chris@16
|
52
|
Chris@16
|
53 tag operator++(any const&);
|
Chris@16
|
54 tag operator++(any const&,int);
|
Chris@16
|
55
|
Chris@16
|
56 # endif
|
Chris@16
|
57
|
Chris@16
|
58 # if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3202)) \
|
Chris@16
|
59 || BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
|
Chris@16
|
60 # define BOOST_comma(a,b) (a)
|
Chris@16
|
61 # else
|
Chris@16
|
62 // In case an operator++ is found that returns void, we'll use ++x,0
|
Chris@16
|
63 tag operator,(tag,int);
|
Chris@16
|
64 # define BOOST_comma(a,b) (a,b)
|
Chris@16
|
65 # endif
|
Chris@16
|
66
|
Chris@16
|
67 # if defined(BOOST_MSVC)
|
Chris@16
|
68 # pragma warning(push)
|
Chris@16
|
69 # pragma warning(disable:4913) // Warning about operator,
|
Chris@16
|
70 # endif
|
Chris@16
|
71
|
Chris@16
|
72 // two check overloads help us identify which operator++ was picked
|
Chris@16
|
73 char (& check_(tag) )[2];
|
Chris@16
|
74
|
Chris@16
|
75 template <class T>
|
Chris@16
|
76 char check_(T const&);
|
Chris@16
|
77
|
Chris@16
|
78
|
Chris@16
|
79 template <class T>
|
Chris@16
|
80 struct impl
|
Chris@16
|
81 {
|
Chris@16
|
82 static typename boost::remove_cv<T>::type& x;
|
Chris@16
|
83
|
Chris@16
|
84 BOOST_STATIC_CONSTANT(
|
Chris@16
|
85 bool
|
Chris@16
|
86 , value = sizeof(is_incrementable_::check_(BOOST_comma(++x,0))) == 1
|
Chris@16
|
87 );
|
Chris@16
|
88 };
|
Chris@16
|
89
|
Chris@16
|
90 template <class T>
|
Chris@16
|
91 struct postfix_impl
|
Chris@16
|
92 {
|
Chris@16
|
93 static typename boost::remove_cv<T>::type& x;
|
Chris@16
|
94
|
Chris@16
|
95 BOOST_STATIC_CONSTANT(
|
Chris@16
|
96 bool
|
Chris@16
|
97 , value = sizeof(is_incrementable_::check_(BOOST_comma(x++,0))) == 1
|
Chris@16
|
98 );
|
Chris@16
|
99 };
|
Chris@16
|
100
|
Chris@16
|
101 # if defined(BOOST_MSVC)
|
Chris@16
|
102 # pragma warning(pop)
|
Chris@16
|
103 # endif
|
Chris@16
|
104
|
Chris@16
|
105 }
|
Chris@16
|
106
|
Chris@16
|
107 # undef BOOST_comma
|
Chris@16
|
108
|
Chris@16
|
109 template<typename T>
|
Chris@16
|
110 struct is_incrementable
|
Chris@16
|
111 BOOST_TT_AUX_BOOL_C_BASE(::boost::detail::is_incrementable_::impl<T>::value)
|
Chris@16
|
112 {
|
Chris@16
|
113 BOOST_TT_AUX_BOOL_TRAIT_VALUE_DECL(::boost::detail::is_incrementable_::impl<T>::value)
|
Chris@16
|
114 BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_incrementable,(T))
|
Chris@16
|
115 };
|
Chris@16
|
116
|
Chris@16
|
117 template<typename T>
|
Chris@16
|
118 struct is_postfix_incrementable
|
Chris@16
|
119 BOOST_TT_AUX_BOOL_C_BASE(::boost::detail::is_incrementable_::impl<T>::value)
|
Chris@16
|
120 {
|
Chris@16
|
121 BOOST_TT_AUX_BOOL_TRAIT_VALUE_DECL(::boost::detail::is_incrementable_::postfix_impl<T>::value)
|
Chris@16
|
122 BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_postfix_incrementable,(T))
|
Chris@16
|
123 };
|
Chris@16
|
124
|
Chris@16
|
125 } // namespace detail
|
Chris@16
|
126
|
Chris@16
|
127 BOOST_TT_AUX_TEMPLATE_ARITY_SPEC(1, ::boost::detail::is_incrementable)
|
Chris@16
|
128 BOOST_TT_AUX_TEMPLATE_ARITY_SPEC(1, ::boost::detail::is_postfix_incrementable)
|
Chris@16
|
129
|
Chris@16
|
130 } // namespace boost
|
Chris@16
|
131
|
Chris@16
|
132 # include <boost/type_traits/detail/bool_trait_undef.hpp>
|
Chris@16
|
133
|
Chris@16
|
134 #endif // IS_INCREMENTABLE_DWA200415_HPP
|