From bb438874301e0b3b38d8c47c359975d4572eb5ee Mon Sep 17 00:00:00 2001 From: Tim Blechmann Date: Sun, 17 Jan 2016 11:40:55 +0100 Subject: [PATCH] irange: introduce one-parameter variant of irange this simplifies the use of boost::irange, as boost::irange( 0, foo ); may compile or not depending on the platform-specific integer type of foo, requiring an explicit cast of 0 to decltype(foo). --- doc/reference/ranges/irange.qbk | 7 +++-- include/boost/range/irange.hpp | 11 +++++-- test/irange.cpp | 52 ++++++++++++++++++++++++++++----- 3 files changed, 59 insertions(+), 11 deletions(-) diff --git a/doc/reference/ranges/irange.qbk b/doc/reference/ranges/irange.qbk index 6e59cb1..1d4ae7e 100644 --- a/doc/reference/ranges/irange.qbk +++ b/doc/reference/ranges/irange.qbk @@ -10,7 +10,11 @@ `` template iterator_range< range_detail::integer_iterator > -irange(Integer first, Integer last); +irange(Integer last); + +template +iterator_range< range_detail::integer_iterator > +irange(Integer first, Integer last); template iterator_range< range_detail::integer_iterator_with_step > @@ -37,4 +41,3 @@ Defined in the header file `boost/range/irange.hpp` Constant. Since this function generates a new range the most significant performance cost is incurred through the iteration of the generated range. [endsect] - diff --git a/include/boost/range/irange.hpp b/include/boost/range/irange.hpp index b1a1240..7d5fee5 100644 --- a/include/boost/range/irange.hpp +++ b/include/boost/range/irange.hpp @@ -217,7 +217,7 @@ namespace boost { BOOST_ASSERT( step_size != 0 ); BOOST_ASSERT( (step_size > 0) ? (last >= first) : (last <= first) ); - + typedef typename range_detail::integer_iterator_with_step iterator_t; const std::ptrdiff_t sz = static_cast(step_size >= 0 ? step_size : -step_size); @@ -225,12 +225,19 @@ namespace boost const Integer f = step_size >= 0 ? first : last; const std::ptrdiff_t num_steps = (l - f) / sz + ((l - f) % sz ? 1 : 0); BOOST_ASSERT(num_steps >= 0); - + return strided_integer_range( iterator_t(first, 0, step_size), iterator_t(first, num_steps, step_size)); } + template + integer_range + irange(Integer last) + { + return integer_range(static_cast(0), last); + } + } // namespace boost #endif // include guard diff --git a/test/irange.cpp b/test/irange.cpp index 659401b..7e1a564 100644 --- a/test/irange.cpp +++ b/test/irange.cpp @@ -18,6 +18,23 @@ namespace boost { + // Test an integer range with a step size of 1. + template + void test_irange_impl(Integer last) + { + std::vector reference; + for (Integer i = static_cast(0); i < last; ++i) + { + reference.push_back(i); + } + + std::vector test; + boost::push_back(test, boost::irange(last)); + + BOOST_CHECK_EQUAL_COLLECTIONS( test.begin(), test.end(), + reference.begin(), reference.end() ); + } + // Test an integer range with a step size of 1. template void test_irange_impl(Integer first, Integer last) @@ -34,36 +51,52 @@ namespace boost BOOST_CHECK_EQUAL_COLLECTIONS( test.begin(), test.end(), reference.begin(), reference.end() ); } - + // Test an integer range with a runtime specified step size. template void test_irange_impl(IntegerInput first, IntegerInput last, int step) { BOOST_ASSERT( step != 0 ); - + // Skip tests that have negative values if the type is // unsigned if ((static_cast(static_cast(first)) != first) || (static_cast(static_cast(last)) != last)) return; - + std::vector reference; const std::ptrdiff_t first_p = static_cast(first); const std::ptrdiff_t last_p = static_cast(last); const std::ptrdiff_t step_p = static_cast(step); - for (std::ptrdiff_t current_value = first_p; + for (std::ptrdiff_t current_value = first_p; step_p >= 0 ? current_value < last_p : current_value > last_p; current_value += step_p) reference.push_back(current_value); std::vector test; boost::push_back(test, boost::irange(first, last, step)); - + BOOST_CHECK_EQUAL_COLLECTIONS( test.begin(), test.end(), reference.begin(), reference.end() ); } + // Test driver function that for an integer range [first, last) + // drives the test implementation through various integer + // types. + void test_irange(int last) + { + test_irange_impl(last); + test_irange_impl(last); + test_irange_impl(last); + test_irange_impl(last); + test_irange_impl(last); + test_irange_impl(last); + test_irange_impl(last); + test_irange_impl(last); + } + + // Test driver function that for an integer range [first, last) // drives the test implementation through various integer // types. @@ -102,6 +135,11 @@ namespace boost // number of implementation branches. void irange_unit_test() { + // Test the single-step version of irange(last) + test_irange(0); + test_irange(1); + test_irange(10); + // Test the single-step version of irange(first, last) test_irange(0, 0); test_irange(0, 1); @@ -124,14 +162,14 @@ namespace boost test_irange(9, -9, -2); test_irange(10, 20, 5); test_irange(20, 10, -5); - + test_irange(0, 0, 3); test_irange(0, 1, 3); test_irange(0, 2, 3); test_irange(0, 3, 3); test_irange(0, 4, 3); test_irange(0, 10, 3); - + test_irange(0, 0, -3); test_irange(0, -1, -3); test_irange(0, -2, -3);