diff --git a/include/boost/range/iterator_range_core.hpp b/include/boost/range/iterator_range_core.hpp index c1822fb..b2e7d5f 100755 --- a/include/boost/range/iterator_range_core.hpp +++ b/include/boost/range/iterator_range_core.hpp @@ -298,14 +298,22 @@ namespace boost return m_Begin[at]; } #else - BOOST_DEDUCED_TYPENAME boost::detail::operator_brackets_result::type - operator[]( difference_type at ) const - { - BOOST_ASSERT( at >= 0 && at < size() ); - - typedef boost::detail::use_operator_brackets_proxy use_proxy; - return boost::detail::make_operator_brackets_result(m_Begin + at, use_proxy()); - } + // Using the operator_brackets_result mechanism properly supports + // the corner cases with proxies for references etc. However + // the operator_brackets_result implementation does not support + // pointers as iterators. Since a pointer can't have the + // issues with proxies this implementation uses a simpler + // implementation if the iterator is a pointer. + BOOST_DEDUCED_TYPENAME boost::mpl::if_< + boost::is_pointer, + reference, + BOOST_DEDUCED_TYPENAME boost::detail::operator_brackets_result::type + >::type + operator[]( difference_type at ) const + { + BOOST_ASSERT( at >= 0 && at < size() ); + return get_at(m_Begin, at); + } #endif // @@ -332,6 +340,27 @@ namespace boost } private: + template + static BOOST_DEDUCED_TYPENAME boost::enable_if< + boost::is_pointer, + reference + >::type + get_at( Iterator it, difference_type at ) + { + return it[at]; + } + + template + static BOOST_DEDUCED_TYPENAME boost::disable_if< + boost::is_pointer, + BOOST_DEDUCED_TYPENAME boost::detail::operator_brackets_result::type + >::type + get_at( Iterator it, difference_type at ) + { + typedef boost::detail::use_operator_brackets_proxy use_proxy; + return boost::detail::make_operator_brackets_result(it + at, use_proxy()); + } + // begin and end iterators IteratorT m_Begin; IteratorT m_End; diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 97600d5..965e3cc 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -133,6 +133,7 @@ test-suite range : # [ range-test mfc : $(VC71_ROOT)/atlmfc/include ] [ range-test join ] [ range-test partial_workaround ] + [ range-test pointer_as_iterator ] [ range-test reversible_range ] [ range-test std_container ] [ range-test string ] diff --git a/test/pointer_as_iterator.cpp b/test/pointer_as_iterator.cpp new file mode 100644 index 0000000..e0e28d0 --- /dev/null +++ b/test/pointer_as_iterator.cpp @@ -0,0 +1,39 @@ +// Boost.Range library +// +// Copyright Neil Groves 2010. 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include +#include +#include +#include +#include +#include +#include +#include + +namespace +{ + void test_pointer_as_iterator() + { + boost::array arr; + boost::iterator_range r(arr.begin(), arr.end()); + r[0]; + } +} // anonymous namespace + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.pointer_as_iterator" ); + + test->add(BOOST_TEST_CASE( &test_pointer_as_iterator )); + + return test; +}