1 // Copyright David Abrahams 2003. 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_LVALUE_ITERATOR_DWA2003112_HPP 5 # define IS_LVALUE_ITERATOR_DWA2003112_HPP 6 7 #include <boost/detail/workaround.hpp> 8 9 #include <boost/type_traits/add_lvalue_reference.hpp> 10 #include <boost/iterator/detail/any_conversion_eater.hpp> 11 #include <boost/mpl/bool.hpp> 12 #include <boost/mpl/aux_/lambda_support.hpp> 13 14 #include <iterator> 15 16 // should be the last #includes 17 #include <boost/type_traits/integral_constant.hpp> 18 #include <boost/iterator/detail/config_def.hpp> 19 20 #ifndef BOOST_NO_IS_CONVERTIBLE 21 22 namespace boost { 23 24 namespace iterators { 25 26 namespace detail 27 { 28 #ifndef BOOST_NO_LVALUE_RETURN_DETECTION 29 // Calling lvalue_preserver( <expression>, 0 ) returns a reference 30 // to the expression's result if <expression> is an lvalue, or 31 // not_an_lvalue() otherwise. 32 struct not_an_lvalue {}; 33 34 template <class T> 35 T& lvalue_preserver(T&, int); 36 37 template <class U> 38 not_an_lvalue lvalue_preserver(U const&, ...); 39 40 # define BOOST_LVALUE_PRESERVER(expr) detail::lvalue_preserver(expr,0) 41 42 #else 43 44 # define BOOST_LVALUE_PRESERVER(expr) expr 45 46 #endif 47 48 // Guts of is_lvalue_iterator. Value is the iterator's value_type 49 // and the result is computed in the nested rebind template. 50 template <class Value> 51 struct is_lvalue_iterator_impl 52 { 53 // Eat implicit conversions so we don't report true for things 54 // convertible to Value const& 55 struct conversion_eater 56 { 57 conversion_eater(typename add_lvalue_reference<Value>::type); 58 }; 59 60 static char tester(conversion_eater, int); 61 static char (& tester(any_conversion_eater, ...) )[2]; 62 63 template <class It> 64 struct rebind 65 { 66 static It& x; 67 68 BOOST_STATIC_CONSTANT( 69 bool 70 , value = ( 71 sizeof( 72 is_lvalue_iterator_impl<Value>::tester( 73 BOOST_LVALUE_PRESERVER(*x), 0 74 ) 75 ) == 1 76 ) 77 ); 78 }; 79 }; 80 81 #undef BOOST_LVALUE_PRESERVER 82 83 // 84 // void specializations to handle std input and output iterators 85 // 86 template <> 87 struct is_lvalue_iterator_impl<void> 88 { 89 template <class It> 90 struct rebind : boost::mpl::false_ 91 {}; 92 }; 93 94 #ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS 95 template <> 96 struct is_lvalue_iterator_impl<const void> 97 { 98 template <class It> 99 struct rebind : boost::mpl::false_ 100 {}; 101 }; 102 103 template <> 104 struct is_lvalue_iterator_impl<volatile void> 105 { 106 template <class It> 107 struct rebind : boost::mpl::false_ 108 {}; 109 }; 110 111 template <> 112 struct is_lvalue_iterator_impl<const volatile void> 113 { 114 template <class It> 115 struct rebind : boost::mpl::false_ 116 {}; 117 }; 118 #endif 119 120 // 121 // This level of dispatching is required for Borland. We might save 122 // an instantiation by removing it for others. 123 // 124 template <class It> 125 struct is_readable_lvalue_iterator_impl 126 : is_lvalue_iterator_impl< 127 BOOST_DEDUCED_TYPENAME std::iterator_traits<It>::value_type const 128 >::template rebind<It> 129 {}; 130 131 template <class It> 132 struct is_non_const_lvalue_iterator_impl 133 : is_lvalue_iterator_impl< 134 BOOST_DEDUCED_TYPENAME std::iterator_traits<It>::value_type 135 >::template rebind<It> 136 {}; 137 } // namespace detail 138 139 template< typename T > struct is_lvalue_iterator 140 : public ::boost::integral_constant<bool,::boost::iterators::detail::is_readable_lvalue_iterator_impl<T>::value> 141 { 142 public: 143 BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_lvalue_iterator,(T)) 144 }; 145 146 template< typename T > struct is_non_const_lvalue_iterator 147 : public ::boost::integral_constant<bool,::boost::iterators::detail::is_non_const_lvalue_iterator_impl<T>::value> 148 { 149 public: 150 BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_non_const_lvalue_iterator,(T)) 151 }; 152 153 } // namespace iterators 154 155 using iterators::is_lvalue_iterator; 156 using iterators::is_non_const_lvalue_iterator; 157 158 } // namespace boost 159 160 #endif 161 162 #include <boost/iterator/detail/config_undef.hpp> 163 164 #endif // IS_LVALUE_ITERATOR_DWA2003112_HPP 165