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