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