gpt4 book ai didi

c++ - 是否可以将虚函数和函数对象混合使用 std 算法?

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:46:24 24 4
gpt4 key购买 nike

比如有一个包系统:

class BagBase
{
public:
typedef std::vector<BagObj*> ObjVec;
virtual ObjVec FindObjs(const FinderBase& finder);
protected:
ObjVec Objs;
}

class Bag1 : public BagBase
{
public:
typedef std::vector<MyBagObj*> MyObjVec;
virtual ObjVec FindObjs(const FinderBase& finder);
// ignore ObjVec Objs in BagBase,
// store objects with another type (with more information)
// but you can still extract BagObj* from MyObjs through FindObjs
private:
MyObjVec MyObjs;
}

class Bag2 : public BagBase
{
// just use FindObjs defined in BagBase
}

我想使用 std::find_if 实现 FindObjs,例如:

struct FinderBase
{
virtual bool operator()(BagObj* o);
};

struct Finder1 : public FinderBase
{
virtual bool operator()(BagObj* o);
};

// and Finder2, Finder3, so on, each target to find by different conditions

并实现 virtual ObjVec BagBase::FindObjs(const FinderBase& finder); 如下:

virtual ObjVec BagBase::FindObjs(const FinderBase& finder)
{
ObjVec results;
// a while loop execute std::find_if each time
// below is just a concept
while (...)
{
ObjVec::iterator it = std::find_if(Objs.begin(), Objs.end(), finder);
if (it != Objs.end())
{
results.push_back(*it);
}
++it;
}
}

因为 Bag1 使用了其他类型的 vector ,它可能看起来像:

virtual ObjVec Bag1::FindObjs(const FinderBase& finder)
{
ObjVec results;
while (...)
{
// the difference: MyObjVec
MyObjVec::iterator it = std::find_if(Objs.begin(), Objs.end(), finder);
if (it != Objs.end())
{
// extract Obj* from MyObj*
MyObj* my_obj = (*it);
Obj* obj = my_obj->obj;
results.push_back(obj);
}
++it;
}
}

所以问题是,std::find_if 复制了 finder,所以它确实知道它的实际类型(它可能是 Finder1Finder2),它只是像 FinderBase 对象一样进行复制。

FindObjsvirtual是必须的,因为vector种类繁多,所以无法通过finder 中使用template,但这与std::find_if 的需求直接矛盾,不能推导出finder 的实际类型.

那么这个问题有什么更好的解决方案呢?是否可以混合使用 virtualtemplate 东西?谢谢!

附言需要C++03的解决方案,谢谢!

最佳答案

finder 对象包装在 reference_wrapper 中. refcref 可用于创建一个。

MyObjVec::iterator it = std::find_if(Objs.begine(), Objs.end(), std::ref(finder));

如果您使用的是 C++11 之前的编译器,则有 Boost.Ref

编辑:
正如评论中指出的那样,简单地将 std::ref 替换为 boost::ref 是行不通的。这是因为 boost::reference_wrapperstd::reference_wrapper 不同,缺少 operator() .仅当 std::reference_wrapper 包装一个 callable 对象时,此运算符才参与重载决议,从而允许它作为可调用对象透明地运行。

要从 Boost 获得相同的功能,我们需要使用 boost::bind 来调用包装在 boost::reference_wrapper 中的可调用对象。

MyObjVec::iterator it = std::find_if(Objs.begine(), Objs.end(), 
boost::bind<bool>(boost::ref(finder), _1));

Live demo显示 std::refboost::ref 的用法。

关于c++ - 是否可以将虚函数和函数对象混合使用 std 算法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21200515/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com