在向量中搜索对象的任何实例时出错

时间:2017-10-23 20:37:54

标签: c++ vector

我有一个名为实体的矢量。我想检查它是否包含NPC类的任何实例。这是我到目前为止所做的。

if (std::find(entities.begin(), entities.end(), NPC()) != entities.end()) 
    std::cout << "contains NPCs" << std::endl;

当我尝试编译它时,我得到错误,“binary'==':找不到运算符,它采用'const NPC'类型的右手操作数”。

另外,有谁能告诉我如何检查相反的情况?也就是说,如何检查向量是否包含任何NPC?

编辑:

我将此添加到我的头文件

inline bool operator==(const NPC& lhs, const NPC& rhs)
{
    return std::is_base_of<Entity, NPC>::value;
}

但我收到错误'std :: is_base_of':'_Der'的模板参数无效“

我以为我告诉它检查NPC是否是Entity类的子类,但也许我做错了。即使是这样,那甚至会解决问题吗?对不起,我只是不熟悉operaror重载。我对c ++很新。

1 个答案:

答案 0 :(得分:2)

我的观点:operator==是在这里使用的错误工具,因为这不是测试相等性。这是一项测试,以查看给定的Entity是否为NPC。因此我建议std::find_iffind_if允许我们指定不同的测试。

我能想出的最简单,最容易理解的测试是

bool isNPC(const Entity * const & entity)
{
    // a dynamic_cast returns nullptr if entity cannot be cast to an NPC *
    return dynamic_cast<const NPC*>(entity) != nullptr;
}

我无法想到一个比这更复杂的理由。

isNPC可能而且可能应该是一个lambda,但为了尽可能清楚这一点,我将它留给自由函数。模板此功能,您可以将其用于EntityMonster的任何子项。

用法如下:

void test(const std::vector<Entity *> & entities)
{
    if (std::find_if(entities.begin(), entities.end(), isNPC) != entities.end())
    {
        std::cout << "found NPC\n";
    }
    else
    {
        std::cout << "No NPCs\n";
    }
}

警告:这也将捕获NPC的子类。

here find_if_not也应引起您的兴趣。

修改

Lambda版本(C ++ 14或更新版本。它是一个丑陋的傻瓜,比C ++ 11中的免费功能版本好不了多少):

if (std::find_if(entities.begin(), 
                 entities.end(), 
                 [](auto & entity)->bool
                 {
                     return dynamic_cast<const NPC*>(entity) != nullptr;
                 }) != entities.end())
{
    std::cout << "found\n";
}
else
{
    std::cout << "not found\n";
}

我喜欢免费功能的原因,如上所述,你可以

template <class TYPE>
bool isChild(const Entity * const & entity)
{
    // a dynamic_cast returns nullptr if entity cannot be cast to an NPC *
    return dynamic_cast<const TYPE*>(entity) != nullptr;
}

然后

std::find_if(entities.begin(), entities.end(), isChild<Ninja>)

去寻找忍者。对于您自己搜索的每种类型,您不必一遍又一遍地编写相同的darn函数或lambda等效函数。

如果您使用一次或两次,请转到lambda。如果您怀疑自己将要找更多的孩子,请使用模板。除非现在有模板化的lambdas。那些会很酷。