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

发布于 2024-12-19 09:33:04 字数 1360 浏览 2 评论 0原文

我有一个类 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 函数以便我可以将谓词传递给它?我尝试了多种方法,但到目前为止还没有运气。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

╭⌒浅淡时光〆 2024-12-26 09:33:04

使用模板接受您需要的任何类型

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) 文件中。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文