为具有特定字段的成员搜索通用范围

Searching a Generic Range for a Member with a Specific Field

这是我的模板函数:

template<class DataStruct>
    static bool isPlayerIn(DataStruct players, int id){
        for(DataStruct::iterator player = players.begin();
                player != players.end(); ++player){
            if((*player)->_id == id){
                return true;
            }
        }
        return false;
    }

我希望它能够让玩家作为矢量和地图,或任何其他 STL。我不能使用算法查找,因为我正在搜索 "player",其内部字段 ID 与给定参数相同。这项工作有什么办法吗?

它抱怨:

(*player)->_id

因为它不知道 player 是 ptr to ptr to Player class.

你的封装有问题,因为函数不知道 DataStruct 是什么,它不能直接 de-reference 它的内部迭代器。 如果您为迭代器实现一个 de-reference 运算符,它将起作用。

在迭代器中添加:

objStored *operator(){
    return **this;
}

然后在你的播放器obj中添加一个获取id的方法:

int getId(){
return this->id;
}

而不是 (*player)->_id == id(*player)->getId()

这样,任何 class 在迭代器中包含(以任何方式)支持(以任何方式)getId 方法的对象的对象都将起作用。

如果您使用模板创建通用函数,则不应创建它,因此它仅适用于具有迭代器的 class,该迭代器是指向具有 _id 的玩家的指针成员。 尽量少假设你的对象。

使用C++11,可以轻松使用find_if with a lambda function:

[=](const typename DataStruct::value_type &v){return v._id == id;}

你会在哪里使用类似

auto has_id = [=](const typename DataStruct::value_type &v){return v._id == id;};

return std::find_if(
    std::begin(players),
    std::end(players),
    has_id) != std::end(players);

既然你要求它,你可以把 lambda 放在一个 isSameID 函数中,如果它会在多个地方使用的话。当您进行代码维护时,它也可能会使它更容易阅读。

template <class ContType>
bool isSameID(ContType cont, int id) {
    auto found = find_if(begin(cont), end(cont), [id] (auto item) {
        return item->_id == id;
    });
   return found != end(cont);
}

此函数假定已传递容器并且您使用的是 c++14。

更新 1: 使其同时适用于 mapvector 的最快方法是将 _id 检索从函数中分离出来,让编译器选择正确的方法来获取 [=15] =] 对于给定的容器类型。我还根据您的要求删除了 auto 并切换为通过 const& 传递容器以避免复制:

    int GetID(const pair<int, Player*>& item) {
        return item.second->_id;
    }
    int GetID(Player* item) {
        return item->_id;
    }

    template <class ContType>
        bool isSameID(const ContType& cont, int id) {
            typename ContType::const_iterator found = find_if(begin(cont), end(cont),
               [id] (typename ContType::value_type item) {
                return GetID(item) == id;
            });
           return found != end(cont);
        }