forked from boostorg/range
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).
This commit is contained in:
@ -10,7 +10,11 @@
|
||||
``
|
||||
template<class Integer>
|
||||
iterator_range< range_detail::integer_iterator<Integer> >
|
||||
irange(Integer first, Integer last);
|
||||
irange(Integer last);
|
||||
|
||||
template<class Integer>
|
||||
iterator_range< range_detail::integer_iterator<Integer> >
|
||||
irange(Integer first, Integer last);
|
||||
|
||||
template<class Integer, class StepSize>
|
||||
iterator_range< range_detail::integer_iterator_with_step<Integer, StepSize> >
|
||||
@ -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]
|
||||
|
||||
|
@ -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<Integer> iterator_t;
|
||||
|
||||
const std::ptrdiff_t sz = static_cast<std::ptrdiff_t>(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<Integer>(
|
||||
iterator_t(first, 0, step_size),
|
||||
iterator_t(first, num_steps, step_size));
|
||||
}
|
||||
|
||||
template<typename Integer>
|
||||
integer_range<Integer>
|
||||
irange(Integer last)
|
||||
{
|
||||
return integer_range<Integer>(static_cast<Integer>(0), last);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // include guard
|
||||
|
@ -18,6 +18,23 @@
|
||||
|
||||
namespace boost
|
||||
{
|
||||
// Test an integer range with a step size of 1.
|
||||
template<typename Integer>
|
||||
void test_irange_impl(Integer last)
|
||||
{
|
||||
std::vector<Integer> reference;
|
||||
for (Integer i = static_cast<Integer>(0); i < last; ++i)
|
||||
{
|
||||
reference.push_back(i);
|
||||
}
|
||||
|
||||
std::vector<Integer> 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<typename Integer>
|
||||
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<typename Integer, typename IntegerInput>
|
||||
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<IntegerInput>(static_cast<Integer>(first)) != first)
|
||||
|| (static_cast<IntegerInput>(static_cast<Integer>(last)) != last))
|
||||
return;
|
||||
|
||||
|
||||
std::vector<Integer> reference;
|
||||
|
||||
const std::ptrdiff_t first_p = static_cast<std::ptrdiff_t>(first);
|
||||
const std::ptrdiff_t last_p = static_cast<std::ptrdiff_t>(last);
|
||||
const std::ptrdiff_t step_p = static_cast<std::ptrdiff_t>(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<Integer> 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<signed char>(last);
|
||||
test_irange_impl<unsigned char>(last);
|
||||
test_irange_impl<signed short>(last);
|
||||
test_irange_impl<unsigned short>(last);
|
||||
test_irange_impl<signed int>(last);
|
||||
test_irange_impl<unsigned int>(last);
|
||||
test_irange_impl<signed long>(last);
|
||||
test_irange_impl<unsigned long>(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);
|
||||
|
Reference in New Issue
Block a user