shifting elements of a container

I played a little bit with the rotating of container elements (after I saw a possible solution here in the forum).

I made a rotating function which works on forward-based iterators. But it has two iteration loops which will be nested.

Then I tried to make a solution which would work on random-access iterators which should work with only one iteration loop. My try works only with a shifting by one position.

So I ask: Is it be able making such a shifting function with only one iterative loop? And without copying/moving one container into another.

Here is my code so far:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <iostream>

// Rotates all elements leftward by 'size' positions.
// Works with any forward iterator.
//
template <typename Itr>
void rotate_left( const Itr begin, const Itr end, std::size_t rotate_by)
{
    if (begin == end) return;
    auto pos = begin, pos2 = begin;
    ++pos2;
    if (pos2 == end) return;
    
    for( std::size_t n = 0; n < rotate_by; ++n)
    {
        pos2 = pos = begin;
        ++pos2;
        auto tmp = std::move(*pos);
        Itr last;
        do
        {
            last = pos2;
            *pos++ = std::move( *pos2++);
        }
        while (pos2 != end);
        *last = tmp;
    }
}


// Should work with any random access iterator
//
// The question is: Is it able to rotate all elements without nested loops?
//
template <typename Itr>
void rotate_left_with_random_access( const Itr begin, const Itr end, int rotate_by)
{
    if (begin == end) return; // Empty container.
    
    const int range = end - begin;
    rotate_by %= range; // Rotate only in matching range.    
    for (int i = 0; i < range-1; ++i)
    {
        auto tmp = std::move(begin[i]);
        begin[i] = std::move( begin[(i+rotate_by)%range]);
        begin[(i+rotate_by)%range] = std::move(tmp);
    }
}


int main()
{
    char word[] = "0123456789";
    rotate_left_with_random_access(word, word+4, 1);
    std::cout << word;
}
Topic archived. No new replies allowed.