diff --git a/include/boost/iterator/is_lvalue_iterator.hpp b/include/boost/iterator/is_lvalue_iterator.hpp new file mode 100755 index 0000000..a89b373 --- /dev/null +++ b/include/boost/iterator/is_lvalue_iterator.hpp @@ -0,0 +1,148 @@ +// Copyright David Abrahams 2003. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef IS_LVALUE_ITERATOR_DWA2003112_HPP +# define IS_LVALUE_ITERATOR_DWA2003112_HPP + +#include +#include +#include + +// should be the last #include +#include +#include + +namespace boost { + +namespace detail +{ +#ifndef BOOST_NO_LVALUE_RETURN_DETECTION + // Calling lvalue_preserver( , 0 ) returns a reference + // to the expression's result if is an lvalue, or + // not_an_lvalue() otherwise. + struct not_an_lvalue {}; + + template + T& lvalue_preserver(T&, int); + + template + not_an_lvalue lvalue_preserver(U const&, ...); + +# define BOOST_LVALUE_PRESERVER(expr) lvalue_preserver(expr,0) + +#else + +# define BOOST_LVALUE_PRESERVER(expr) expr + +#endif + + struct any_conversion_eater + { + template + any_conversion_eater(T const&); + }; + + // Guts of is_lvalue_iterator. Value is the iterator's value_type + // and the result is computed in the nested rebind template. + template + struct is_lvalue_iterator_impl + { + // Eat implicit conversions so we don't report true for things + // convertible to Value const& + struct conversion_eater + { + conversion_eater(Value&); + }; + + static char tester(conversion_eater, int); + static char (& tester(any_conversion_eater, ...) )[2]; + + template + struct rebind + { + static It& x; + + BOOST_STATIC_CONSTANT( + bool + , value = ( + sizeof( + is_lvalue_iterator_impl::tester( + BOOST_LVALUE_PRESERVER(*x), 0 + ) + ) == 1 + ) + ); + }; + }; + +#undef BOOST_LVALUE_PRESERVER + + // + // void specializations to handle std input and output iterators + // + template <> + struct is_lvalue_iterator_impl + { + template + struct rebind : boost::mpl::false_ + {}; + }; + +#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS + template <> + struct is_lvalue_iterator_impl + { + template + struct rebind : boost::mpl::false_ + {}; + }; + + template <> + struct is_lvalue_iterator_impl + { + template + struct rebind : boost::mpl::false_ + {}; + }; + + template <> + struct is_lvalue_iterator_impl + { + template + struct rebind : boost::mpl::false_ + {}; + }; +#endif + + // + // This level of dispatching is required for Borland. We might save + // an instantiation by removing it for others. + // + template + struct is_readable_lvalue_iterator_impl + : is_lvalue_iterator_impl< + BOOST_DEDUCED_TYPENAME boost::detail::iterator_traits::value_type const + >::template rebind + {}; + + template + struct is_writable_lvalue_iterator_impl + : is_lvalue_iterator_impl< + BOOST_DEDUCED_TYPENAME boost::detail::iterator_traits::value_type + >::template rebind + {}; +} // namespace detail + +// Define the trait with full mpl lambda capability and various broken +// compiler workarounds +BOOST_TT_AUX_BOOL_TRAIT_DEF1( + is_readable_lvalue_iterator,T,::boost::detail::is_readable_lvalue_iterator_impl::value) + +BOOST_TT_AUX_BOOL_TRAIT_DEF1( + is_writable_lvalue_iterator,T,::boost::detail::is_writable_lvalue_iterator_impl::value) + +} // namespace boost + +#include + +#endif // IS_LVALUE_ITERATOR_DWA2003112_HPP diff --git a/test/Jamfile b/test/Jamfile index a7bb4e3..40d869c 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -19,6 +19,7 @@ test-suite iterator [ run is_convertible_fail.cpp ] # These tests should work for just about everything. + [ compile is_lvalue_iterator.cpp ] [ run unit_tests.cpp ] [ run concept_tests.cpp ] [ run iterator_adaptor_cc.cpp ] diff --git a/test/is_lvalue_iterator.cpp b/test/is_lvalue_iterator.cpp new file mode 100755 index 0000000..cf043b7 --- /dev/null +++ b/test/is_lvalue_iterator.cpp @@ -0,0 +1,86 @@ +// Copyright David Abrahams 2003. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#include +#include +#include +#include + +// Last, for BOOST_NO_LVALUE_RETURN_DETECTION +#include + +struct v +{ + v(); + ~v(); +}; + +BOOST_TT_BROKEN_COMPILER_SPEC(v) + +struct value_iterator : boost::iterator +{ + v operator*() const; +}; + +struct noncopyable_iterator : boost::iterator +{ + boost::noncopyable const& operator*() const; +}; + +struct proxy_iterator : boost::iterator +{ +#if BOOST_WORKAROUND(__GNUC__, == 2) + typedef boost::iterator base; + typedef base::iterator_category iterator_category; + typedef base::value_type value_type; + typedef base::difference_type difference_type; + typedef base::pointer pointer; + typedef base::reference reference; +#endif + + struct proxy + { + operator v&() const; + proxy& operator=(v) const; + }; + + proxy operator*() const; +}; + +BOOST_TT_BROKEN_COMPILER_SPEC(proxy_iterator::proxy) + +int main() +{ + BOOST_STATIC_ASSERT(boost::is_readable_lvalue_iterator::value); + BOOST_STATIC_ASSERT(boost::is_readable_lvalue_iterator::value); + BOOST_STATIC_ASSERT(boost::is_readable_lvalue_iterator::iterator>::value); + BOOST_STATIC_ASSERT(boost::is_readable_lvalue_iterator::const_iterator>::value); + BOOST_STATIC_ASSERT(!boost::is_readable_lvalue_iterator > >::value); + BOOST_STATIC_ASSERT(!boost::is_readable_lvalue_iterator >::value); + BOOST_STATIC_ASSERT(!boost::is_readable_lvalue_iterator::value); +#ifndef BOOST_NO_LVALUE_RETURN_DETECTION + BOOST_STATIC_ASSERT(!boost::is_readable_lvalue_iterator::value); +#endif + // Make sure inaccessible copy constructor doesn't prevent + // reference binding + BOOST_STATIC_ASSERT(boost::is_readable_lvalue_iterator::value); + + + BOOST_STATIC_ASSERT(boost::is_writable_lvalue_iterator::value); + BOOST_STATIC_ASSERT(!boost::is_writable_lvalue_iterator::value); + BOOST_STATIC_ASSERT(boost::is_writable_lvalue_iterator::iterator>::value); + BOOST_STATIC_ASSERT(!boost::is_writable_lvalue_iterator::const_iterator>::value); + BOOST_STATIC_ASSERT(!boost::is_writable_lvalue_iterator > >::value); + BOOST_STATIC_ASSERT(!boost::is_writable_lvalue_iterator >::value); + BOOST_STATIC_ASSERT(!boost::is_writable_lvalue_iterator::value); +#ifndef BOOST_NO_LVALUE_RETURN_DETECTION + BOOST_STATIC_ASSERT(!boost::is_writable_lvalue_iterator::value); +#endif + BOOST_STATIC_ASSERT(!boost::is_writable_lvalue_iterator::value); + + return 0; +}