Boost.Range defect fix for the operator[] of iterator_range. This now reverts to a simpler implementation when the iterator is a pointer.

[SVN r61258]
This commit is contained in:
Neil Groves
2010-04-13 20:41:11 +00:00
parent 350a1f8bfc
commit 47b40f66e1
3 changed files with 77 additions and 8 deletions

View File

@ -298,14 +298,22 @@ namespace boost
return m_Begin[at]; return m_Begin[at];
} }
#else #else
BOOST_DEDUCED_TYPENAME boost::detail::operator_brackets_result<iterator, value_type, reference>::type // Using the operator_brackets_result mechanism properly supports
operator[]( difference_type at ) const // the corner cases with proxies for references etc. However
{ // the operator_brackets_result implementation does not support
BOOST_ASSERT( at >= 0 && at < size() ); // pointers as iterators. Since a pointer can't have the
// issues with proxies this implementation uses a simpler
typedef boost::detail::use_operator_brackets_proxy<value_type,reference> use_proxy; // implementation if the iterator is a pointer.
return boost::detail::make_operator_brackets_result<iterator>(m_Begin + at, use_proxy()); BOOST_DEDUCED_TYPENAME boost::mpl::if_<
} boost::is_pointer<iterator>,
reference,
BOOST_DEDUCED_TYPENAME boost::detail::operator_brackets_result<iterator, value_type, reference>::type
>::type
operator[]( difference_type at ) const
{
BOOST_ASSERT( at >= 0 && at < size() );
return get_at(m_Begin, at);
}
#endif #endif
// //
@ -332,6 +340,27 @@ namespace boost
} }
private: private:
template<class Iterator>
static BOOST_DEDUCED_TYPENAME boost::enable_if<
boost::is_pointer<Iterator>,
reference
>::type
get_at( Iterator it, difference_type at )
{
return it[at];
}
template<class Iterator>
static BOOST_DEDUCED_TYPENAME boost::disable_if<
boost::is_pointer<Iterator>,
BOOST_DEDUCED_TYPENAME boost::detail::operator_brackets_result<Iterator, value_type, reference>::type
>::type
get_at( Iterator it, difference_type at )
{
typedef boost::detail::use_operator_brackets_proxy<value_type,reference> use_proxy;
return boost::detail::make_operator_brackets_result<Iterator>(it + at, use_proxy());
}
// begin and end iterators // begin and end iterators
IteratorT m_Begin; IteratorT m_Begin;
IteratorT m_End; IteratorT m_End;

View File

@ -133,6 +133,7 @@ test-suite range :
# [ range-test mfc : <include>$(VC71_ROOT)/atlmfc/include ] # [ range-test mfc : <include>$(VC71_ROOT)/atlmfc/include ]
[ range-test join ] [ range-test join ]
[ range-test partial_workaround ] [ range-test partial_workaround ]
[ range-test pointer_as_iterator ]
[ range-test reversible_range ] [ range-test reversible_range ]
[ range-test std_container ] [ range-test std_container ]
[ range-test string ] [ range-test string ]

View File

@ -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 <boost/range/iterator_range.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/array.hpp>
#include <boost/test/test_tools.hpp>
#include <boost/test/unit_test.hpp>
#include <iostream>
#include <vector>
namespace
{
void test_pointer_as_iterator()
{
boost::array<int,3> arr;
boost::iterator_range<const int*> 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;
}