2011-12-05 10 views
8

Mam klasę CMyVector, która posiada wektor wskaźników do obiektów CMyClass i mam kilka funkcji "znajdowania", aby znaleźć elementy zgodnie z kryteriami differente. Tak na przykład mam:Jak przekazywać predykat jako parametr funkcji

CMyClass* CMyVector::FindByX(int X); 
CMyClass* CMyVector::FindByString(const CString& str); 
CMyClass* CMyVector::FindBySomeOtherClass(CSomeOtherClass* ptr); 
// Other find functions... 

Początkowo były one realizowane jako pętle, przemierzając wektor, szukając elementu, który pasuje X, str, PTR lub cokolwiek. Więc stworzyliśmy predykaty, jak ten jeden:

class IsSameX:public unary_function<CMyClass*, bool> 
{ 
    int num; 
public: 
    IsSameX(int n):num(n){} 
    bool operator()(CMyClass* obj) const 
    { 
     return (obj != NULL && (obj->X() == num)); 
    } 
}; 

a zakończył z wieloma funkcjami, które wszystkie wyglądają tak:

CMyClass* CMyVector::FindByX(int x) 
{ 
    CMyVector::iterator it = find_if(vec.begin(), vec.end(), IsSameX(x)); 
    if (it != vec.end()) 
    { 
     return *it; 
    } 
    return NULL; 
} 

Oni wszyscy wyglądają tak samo, z wyjątkiem orzeczenia, które jest nazywa, więc myślałem uproszczenia więcej i stworzył funkcję jak ten:

CMyClass* CMyVector::Find(ThisIsWhatIDontKnow Predicate) 
{ 
    CMyVector::iterator it = find_if(vec.begin(), vec.end(), Predicate); 
    if (it != vec.end()) 
    { 
     return *it; 
    } 
    return NULL; 
} 

i zrobić:

CMyClass* CMyVector::FindByX(int x) 
{ 
    return Find(IsSameX(x)); 
} 

I tak dalej.

Więc moje pytanie brzmi: W jaki sposób należy zadeklarować moje Find funkcję tak mogę przekazać mu moje predykaty? Próbowałem na kilka sposobów, ale bez powodzenia.

+0

Można owinąć znaleźć szablon w innym szablonie jak sugeruje lub użyj 'const std :: Funkcje i' jako źródłowe parametr. – AJG85

Odpowiedz

10

użycie szablonu do podjęcia w cokolwiek kiedykolwiek wpisać trzeba

template<typename UnaryPredicate> 
CMyClass* CMyVector::Find(UnaryPredicate Predicate) 
{ 
    CMyVector::iterator it = find_if(vec.begin(), vec.end(), Predicate); 
    if (it != vec.end()) 
    { 
     return *it; 
    } 
    return NULL; 
} 

Mogłeś sprecyzowane również użyć std :: function (C++ 11)

CMyClass* CMyVector::Find(std::function<bool(const (CMYClass*)&)> Predicate) 
{ 
    CMyVector::iterator it = find_if(vec.begin(), vec.end(), Predicate); 
    if (it != vec.end()) 
    { 
     return *it; 
    } 
    return NULL; 
} 

Osobiście wolę Top One, ponieważ prawdopodobnie będzie łatwiej kompilatorowi zoptymalizować, ponieważ jest mniej zakłóceń. a jeśli wywołanie jest unikalne, może zostać zainicjowane.

EDIT: Warto również zauważyć, że jeśli ci iść z opcją matrycy, trzeba będzie zapewnić realizację w nagłówku pliku, może to być ból. Natomiast funkcja std :: może żyć w pliku źródłowym (.cpp) we wszystkich innych implementacjach.

+0

Dzięki, nie mam jeszcze C++ 11, więc będę musiał przejść przez szablon. – MikMik