I have a class CMyVector
which holds a vector of pointers to CMyClass
objects and I have several "find" functions to find elements according to differente criteria. So for example, I have:
CMyClass* CMyVector::FindByX(int X);
CMyClass* CMyVector::FindByString(const CString& str);
CMyClass* CMyVector::FindBySomeOtherClass(CSomeOtherClass* ptr);
// Other find functions...
At first, they were implemented as loops, traversing the vector, looking for the element that matches X, str, ptr or whatever. So I've created predicates, like this one:
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));
}
};
And ended with a bunch of functions which all look like this:
CMyClass* CMyVector::FindByX( int x )
{
CMyVector::iterator it = find_if(vec.begin(), vec.end(), IsSameX(x));
if (it != vec.end())
{
return *it;
}
return NULL;
}
They all look the same, except for the predicate that is called, so I've thought of simplifying more, and created a function like this one:
CMyClass* CMyVector::Find( ThisIsWhatIDontKnow Predicate)
{
CMyVector::iterator it = find_if(vec.begin(), vec.end(), Predicate);
if (it != vec.end())
{
return *it;
}
return NULL;
}
And do:
CMyClass* CMyVector::FindByX( int x )
{
return Find(IsSameX(x));
}
And so on.
So my question is: How should I declare my Find
function so I can pass it my predicates? I've tried several ways, but with no luck so far.
use template to take in whatever ever type you need
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;
}
You could alway also use 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;
}
Personally I prefer the top one, because it will probably be easier for the compiler to optimize as there is less indirection. and if the call is unique it might get inlined.
EDIT: It is also worth noting that if go you with the templated option, you will have to provide the implementation in the header file, this can be a pain. Whereas the std::function can live in the source (.cpp) file with all the other implementations.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With