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