mirror of
https://github.com/ETLCPP/etl.git
synced 2026-04-30 19:09:10 +08:00
Fix etl::rotate (#1327)
Per the C++ standard, std::rotate returns first + (last - middle): * When first == middle, return last * When middle == last, return first
This commit is contained in:
parent
7bac1d02f7
commit
a8ebe338f8
@ -1193,7 +1193,12 @@ namespace etl
|
||||
typename etl::enable_if<etl::is_random_access_iterator<TIterator>::value, TIterator>::type
|
||||
rotate_general(TIterator first, TIterator middle, TIterator last)
|
||||
{
|
||||
if (first == middle || middle == last)
|
||||
if (first == middle)
|
||||
{
|
||||
return last;
|
||||
}
|
||||
|
||||
if (middle == last)
|
||||
{
|
||||
return first;
|
||||
}
|
||||
@ -1242,7 +1247,12 @@ namespace etl
|
||||
typename etl::enable_if<etl::is_random_access_iterator<TIterator>::value, TIterator>::type
|
||||
rotate_general(TIterator first, TIterator middle, TIterator last)
|
||||
{
|
||||
if (first == middle || middle == last)
|
||||
if (first == middle)
|
||||
{
|
||||
return last;
|
||||
}
|
||||
|
||||
if (middle == last)
|
||||
{
|
||||
return first;
|
||||
}
|
||||
@ -1292,7 +1302,12 @@ namespace etl
|
||||
typename etl::enable_if<etl::is_bidirectional_iterator<TIterator>::value, TIterator>::type
|
||||
rotate_general(TIterator first, TIterator middle, TIterator last)
|
||||
{
|
||||
if (first == middle || middle == last)
|
||||
if (first == middle)
|
||||
{
|
||||
return last;
|
||||
}
|
||||
|
||||
if (middle == last)
|
||||
{
|
||||
return first;
|
||||
}
|
||||
@ -1314,7 +1329,12 @@ namespace etl
|
||||
typename etl::enable_if<etl::is_forward_iterator<TIterator>::value, TIterator>::type
|
||||
rotate_general(TIterator first, TIterator middle, TIterator last)
|
||||
{
|
||||
if (first == middle || middle == last)
|
||||
if (first == middle)
|
||||
{
|
||||
return last;
|
||||
}
|
||||
|
||||
if (middle == last)
|
||||
{
|
||||
return first;
|
||||
}
|
||||
|
||||
@ -113,6 +113,12 @@ struct non_random_iterator : public etl::iterator<ETL_OR_STD::bidirectional_iter
|
||||
T* ptr;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
bool operator ==(const non_random_iterator<T>& lhs, const non_random_iterator<T>& rhs)
|
||||
{
|
||||
return lhs.ptr == rhs.ptr;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool operator !=(const non_random_iterator<T>& lhs, const non_random_iterator<T>& rhs)
|
||||
{
|
||||
|
||||
@ -1236,6 +1236,93 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(rotate_return_value)
|
||||
{
|
||||
// Verify that etl::rotate returns the same iterator as std::rotate
|
||||
// in all cases, including the degenerate first==middle and middle==last cases.
|
||||
std::vector<int> initial_data = { 1, 2, 3, 4, 5 };
|
||||
|
||||
for (size_t i = 0UL; i <= initial_data.size(); ++i)
|
||||
{
|
||||
std::vector<int> data1(initial_data);
|
||||
std::vector<int> data2(initial_data);
|
||||
|
||||
auto std_result = std::rotate(data1.data(), data1.data() + i, data1.data() + data1.size());
|
||||
auto etl_result = etl::rotate(data2.data(), data2.data() + i, data2.data() + data2.size());
|
||||
|
||||
// Check that the return value offset matches
|
||||
ptrdiff_t std_offset = std_result - data1.data();
|
||||
ptrdiff_t etl_offset = etl_result - data2.data();
|
||||
CHECK_EQUAL(std_offset, etl_offset);
|
||||
}
|
||||
|
||||
// Explicitly test first == middle (empty left half): should return last
|
||||
{
|
||||
std::vector<int> data = { 1, 2, 3 };
|
||||
auto result = etl::rotate(data.data(), data.data(), data.data() + data.size());
|
||||
CHECK(result == data.data() + data.size());
|
||||
}
|
||||
|
||||
// Explicitly test middle == last (empty right half): should return first
|
||||
{
|
||||
std::vector<int> data = { 1, 2, 3 };
|
||||
auto result = etl::rotate(data.data(), data.data() + data.size(), data.data() + data.size());
|
||||
CHECK(result == data.data());
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(rotate_return_value_non_random_iterator)
|
||||
{
|
||||
// Verify that etl::rotate returns the correct iterator when called with
|
||||
// non-random (bidirectional) iterators, exercising rotate_general for
|
||||
// bidirectional iterators rather than the random-access overload.
|
||||
std::vector<int> initial_data = { 1, 2, 3, 4, 5 };
|
||||
|
||||
for (size_t i = 0UL; i <= initial_data.size(); ++i)
|
||||
{
|
||||
std::vector<int> data1(initial_data);
|
||||
std::vector<int> data2(initial_data);
|
||||
|
||||
auto std_result = std::rotate(data1.data(), data1.data() + i, data1.data() + data1.size());
|
||||
|
||||
non_random_iterator<int> nr_first(data2.data());
|
||||
non_random_iterator<int> nr_middle(data2.data() + i);
|
||||
non_random_iterator<int> nr_last(data2.data() + data2.size());
|
||||
auto etl_result = etl::rotate(nr_first, nr_middle, nr_last);
|
||||
|
||||
// Check that the data was rotated correctly
|
||||
bool isEqual = std::equal(std::begin(data1), std::end(data1), std::begin(data2));
|
||||
CHECK(isEqual);
|
||||
|
||||
// Check that the return value offset matches
|
||||
ptrdiff_t std_offset = std_result - data1.data();
|
||||
ptrdiff_t etl_offset = etl_result.ptr - data2.data();
|
||||
CHECK_EQUAL(std_offset, etl_offset);
|
||||
}
|
||||
|
||||
// Explicitly test first == middle (empty left half): should return last
|
||||
{
|
||||
std::vector<int> data = { 1, 2, 3 };
|
||||
non_random_iterator<int> nr_first(data.data());
|
||||
non_random_iterator<int> nr_middle(data.data());
|
||||
non_random_iterator<int> nr_last(data.data() + data.size());
|
||||
auto result = etl::rotate(nr_first, nr_middle, nr_last);
|
||||
CHECK(result.ptr == data.data() + data.size());
|
||||
}
|
||||
|
||||
// Explicitly test middle == last (empty right half): should return first
|
||||
{
|
||||
std::vector<int> data = { 1, 2, 3 };
|
||||
non_random_iterator<int> nr_first(data.data());
|
||||
non_random_iterator<int> nr_middle(data.data() + data.size());
|
||||
non_random_iterator<int> nr_last(data.data() + data.size());
|
||||
auto result = etl::rotate(nr_first, nr_middle, nr_last);
|
||||
CHECK(result.ptr == data.data());
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(any_of)
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user