Как передать предикат в качестве параметра функции



У меня есть класс CMyVector, который содержит вектор указателей на объекты CMyClass, и у меня есть несколько функций "найти", чтобы найти элементы в соответствии с различными критериями. Так, например, у меня есть:



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


Сначала они были реализованы в виде петель, пересекающих вектор, ищущих элемент, который соответствует X, str, ptr или чему-то еще. Поэтому я создал предикаты, такие как этот:



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));
}
};


И закончилась кучей функций, которые все выглядят так:



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


Они все выглядят одинаково. то же самое, за исключением предиката, который называется, поэтому я подумал об упрощении и создал функцию, подобную этой:



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


И сделайте:



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


И так далее.



Итак, мой вопрос: Как я должен объявить свою функцию Find, чтобы я мог передать ей свои предикаты? Я пробовал несколько способов, но пока безуспешно.
977   1  

1 ответ:

Используйте шаблон, чтобы взять все, что вам нужно

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;
}

Вы всегда можете также использовать 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;
}

Лично я предпочитаю верхний, потому что компилятору, вероятно, будет легче оптимизировать, так как меньше косвенности. и если вызов уникален, он может быть встроен.

EDIT: также стоит отметить, что если вы идете с шаблонной опцией, вам придется предоставить реализацию в заголовочном файле, это может быть боль. А std:: функция может жить в источнике (.cpp) файл со всеми другими реализациями.

Comments

    Ничего не найдено.