2013-09-01 37 views

Odpowiedz

18

Przegapiłeś to?

przerzucić rbegin & rend

for_each (A.rbegin(), A.rend(), [](int i) { 
    ... 
}); 

Zwiększenie reverse iterator przesuwa je w kierunku początku pojemnika

+0

Ups, mój błąd! Wielkie dzięki! – user350954

5

std::for_each(A.rbegin(), A.rend(), [](int i) { /*code*/ }); jest proste rozwiązanie.

I zamiast pisało backwards który zaczyna sekwencję, wydobywa z niej begin iterator i end korzystając z bezpłatnego begin i end funkcje (z std::begin i std::endusing deklaracji pobliżu - pełna ADL), tworzy odwrotne iteratory wokół nich, a następnie zwraca sekwencję z tymi dwoma iteratorami odwrotnymi.

Jest to rodzaj schludne, ponieważ masz taką składnię:

for(int i : backwards(A)) { 
    // code 
} 

które łatwiejszy do odczytania niż std::for_each lub ręcznych for pętli.

Ale jestem trochę orzechów.

Oto minimalne backwards. Pełne rozwiązanie lepiej obsługuje adl i kilka przypadków narożnych.

template<class It, class C> 
struct range_for_t{ 
    It b,e; 
    C c; // for lifetime 
    It begin()const{return b;} 
    It end()const{return e;} 
} 
template<class It, class C> 
range_for_t<It,C> range_for(It b,It e,C&& c){ 
    return {std::move(b),std::move(e),std::forward<C>(c)}; 
} 

template<class It> 
range_for_t<It,int> range_for(It b,It e){ 
    return {std::move(b),std::move(e)}; 
} 

Prosty zakres tylko dla zakresu. Można go ulepszyć dzięki doskonałemu przekazywaniu.

Przechodząc C jako pojemnik, który może wymagać przedłużenia żywotności. Jeśli zostanie przekazana jako wartość r, zostanie wykonana kopia, w przeciwnym razie tylko odwołanie. W przeciwnym razie nie jest używany.

Następna część jest proste:

template<class It> 
auto reverse_it(It it){ 
    return std::reverse_iterator<It>(std::move(it)); 
} 
template<class C> 
auto backwards(C&&c){ 
    using std::begin; using std::end; 
    auto b=begin(c), e=end(c); 
    return range_for(
    reverse_it(e),reverse_it(b), 
    std::forward<C>(c) 
); 
} 

To niesprawdzone ale powinno działać.

Jeden ważny test jest zapewnienie, że działa po nakarmić vec rvalue jak:

for(auto x:backwards(make_vec())) 

prac - czyli co poeksperymentować przechowywania C chodzi. Zakłada się również, że ruchome iteratory kontenerów mają ładnie zachowujące się iteratory.

+0

Czy możesz udostępnić kod funkcji "wstecznej" ... – Hashken

+0

@hash sketch added. – Yakk

0

doładowania oferuje funkcję o nazwie reversed, które mogą być używane z C++ 11 range based for loop jak opisuje Yakk w jego odpowiedź:

for(int i : reverse(A)) 
{ 
    // code 
} 

lub

for(int i : A | reversed) 
{ 
    // code 
}