如何将谓词作为函数参数传递

10

我有一个类 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函数,以便我可以将谓词传递给它? 我已经尝试过几种方法,但到目前为止都没有成功。


你可以像建议的那样将模板find包装在另一个模板中,或者使用const std::function&作为谓词参数。 - AJG85
1个回答

13

使用模板来接收您所需的任何类型

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

就我个人而言,我更喜欢使用前面那种方式,因为编译器优化可能会更容易,因为间接引用较少。 如果调用唯一,则可能被内联。

编辑:值得注意的是,如果选择模板选项,则必须在头文件中提供实现,这可能有些麻烦。 而std :: function可以与所有其他实现一起位于源(.cpp)文件中。


谢谢,我还没有C++11,所以我得用模板的方法。 - MikMik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接