2013-06-19 7 views
9

Aby wyszukać pierwsze wystąpienie elementu w C-Array z elementami POD, można to łatwo zrobić za pomocą std::find_if(begin, end, findit). Ale potrzebowałem ostatniego wystąpienia. This answer dał mi pomysł, że można to zrobić z std::reverse_iterator. Tak więc próbowałem:Jak korzystać z find_if wraz z reverse_iterator na tablicy w stylu C?

std::find_if(std::reverse_iterator<podtype*>(end), 
      std::reverse_iterator<podtype*>(begin), 
      findit); 

To dało mi błąd:

cannot convert 'std::reverse_iterator< xyz* > ' to 'xyz*' in assignment

masz pomysł, jak to zrobić w ten sposób, czy znasz lepsze rozwiązanie?

Jest to kod:

#include <iostream> 
#include <iterator> 
#include <algorithm> 

struct xyz { 
    int a; 
    int b; 
}; 

bool findit(const xyz& a) { 
    return (a.a == 2 && a.b == 3); 
} 

int main() { 
    xyz begin[] = { {1, 2}, {2, 3}, {2, 3}, {3, 5} }; 
    xyz* end = begin + 4; 

    // Forward find 
    xyz* found = std::find_if(begin, end, findit); 
    if (found != end) 
     std::cout << "Found at position " 
        << found - begin 
        << std::endl; 

    // Reverse find 
    found = std::find_if(std::reverse_iterator<xyz*>(end), 
         std::reverse_iterator<xyz*>(begin), 
         findit); 
    if (found != std::reverse_iterator<xyz*>(end)); 
     std::cout << "Found at position " 
        << found - std::reverse_iterator<xyz*>(end) 
        << std::endl; 

    return 0; 
} 

A compiler error on codepad.org

Odpowiedz

11

Funkcja std::find_if ma typ zwracanej równą rodzaju iteracyjnej przekazany jako parametr. W twoim przypadku, ponieważ podajesz parametry std::reverse_iterator<xyz*> s, typem powrotu będzie std::reverse_iterator<xyz*>. Oznacza to, że

found = std::find_if(std::reverse_iterator<xyz*>(end), 
        std::reverse_iterator<xyz*>(begin), 
        findit); 

nie będzie kompilować, ponieważ found jest xyz*.

Aby rozwiązać ten problem, można spróbować to:

std::reverse_iterator<xyz*> 
rfound = std::find_if(std::reverse_iterator<xyz*>(end), 
         std::reverse_iterator<xyz*>(begin), 
         findit); 

To będzie naprawić błąd kompilatora. Jednak myślę, że dwa błędy średnie w tej linii:

if (found != std::reverse_iterator<xyz*>(end)); 

pierwsze, trzeba pamiętać, że trzeba średnik po oświadczeniu if, więc ciało rachunku if będą oceniane niezależnie od tego, czy warunek jest spełniony .

Po drugie, należy zwrócić uwagę, że std::find_if zwraca drugi iterator jako wskaźnik, jeśli nic nie pasuje do predykatu. W związku z tym badanie to powinno być

if (rfound != std::reverse_iterator<xyz*>(begin)) 

ponieważ find_if powróci std::reverse_iterator<xyz*>(begin) jeśli element nie zostanie znaleziony.

Mam nadzieję, że to pomoże!

+0

Tak, to pomaga, dziękuję. Zwrócony indeks wynosi teraz 1 w obu przypadkach, co wydaje się właściwe, ale byłoby wspaniale, gdyby wynik odwrotnego znalezienia dałby indeks 2. Nie mogę odjąć 'begin' od' rfound', ponieważ prowadzi to do tego samego błędu co wcześniej . –

+0

@ ChristianAmmer- Myślę, że to dlatego, że twoja logika, aby uzyskać indeks jest błędna. Odejmowanie oblicza odległość od odwrotnego iteratora do ostatniego elementu tablicy, który podaje odległość * od tyłu * tablicy, a nie od przodu. – templatetypedef

+0

Myślę, że mam to teraz. Logika była zła, ale z '(koniec - początek) - (rfound - std :: reverse_iterator (koniec)) - 1" Otrzymuję poprawny indeks. –

Powiązane problemy