2015-11-19 2 views
1

В моем приложении мне нужна возможность пересекать дважды связанный список, начиная с любого произвольного члена списка и продолжая проходить через конец(), обертывая его в начало() и продолжая до тех пор, пока обход достигает, где он начался.Циркулярная итерация std :: list

Я решил использовать std::list для базовой структуры данных и написал процедуру circulate для этого. Однако он показывает некоторое неожиданное поведение, когда оно завершается с end() до begin(). Вот моя реализация

template <class Container, class BiDirIterator> 
void circulate(Container container, BiDirIterator cursor, 
    std::function<void(BiDirIterator current)> processor) 
{ 
    BiDirIterator start = cursor; 
    do { 
    processor(cursor); 
    cursor++; 
    if (cursor == container.end()) { 
     cursor = container.begin(); // [A] 
    } 
    } while (cursor != start); 
} 

// ... 

typedef int T; 
typedef std::list<T> TList; 
typedef TList::iterator TIter; 

int count = 0; 
TList l; 
l.push_back(42); 
circulate<TList, TIter>(
    l, l.begin(), 
    [&](TIter cur) { 
    std::cout << *cur << std::endl; 
    count++; 
    } 
); 

Выход:

42 
-842150451 

Когда я пошагово код, я вижу, что линия, помеченная никогда не достигается [A]. Курсор никогда не равен container.end(). Удивительно, вызывая ++ на этом курсоре, автоматически переходит в container.begin(). (Я полагаю, это специфично для этой реализации STL).

Как я могу исправить это поведение?

ответ

1

Проблема в том, что вы принимаете Container по стоимости. Это вызывает копию, поэтому итераторы, возвращаемые container.end() и container.begin(), не такие же, как итератор, переданный функции. Вместо этого, если вы передадите Container по ссылке, тогда код работает правильно.

Live Example

Смежные вопросы