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