在一个向量中查找结构体

5

我想要查找一个结构,其全部成员数据都匹配特定值。

我编写了以下简短的程序:

#include <iostream>
#include <vector>
using namespace std;
struct vlan {
    int vlanId;
    bool status;
};

vector<vlan> vlanTable; 

int main(){
    vlan tmp;
    tmp.status = true;
    tmp.vlanId = 1;
    vector <vlan>::iterator flag = find(vlanTable.begin(), vlanTable.end(), tmp);
    if ( flag != vlanTable.end()){
        cout<<"found"<<endl;
    }
    else cout<<"not found"<<endl;
    return 0;
}

它返回错误消息为:“模板参数推断 / 替换在 find 函数处失败。”
有人能帮我吗?

8
  1. 你需要写 #include <algorithm>
  2. 你的结构体需要一个 operator== 来确定如何进行等值比较。
- UnholySheep
@Ripi2:我尝试在主函数中填充vlanTable,但是发现仍然出现相同的错误。实际上,我认为我应该能够在空的vlanTable中进行搜索。如果找到项目,则不执行任何操作;如果未找到,则将项目推入向量vlanTable中。因此,vlanTable一开始可能是空的。 - Minh Pham
@UnholySheep:您能详细说明一下吗?我不太明白。谢谢。 - Minh Pham
再次查看您的错误消息--我怀疑“模板参数推导/替换失败”不是完整的消息。应该还有更多。可能会提到“operator ==”。 - Drew Dormann
如果您正在使用Visual Studio,则“错误”窗格仅包含错误“摘要”,完整的错误消息在“输出”窗格中。 - Mooing Duck
3个回答

7
你需要为你的vlan类提供"=="运算符:
struct vlan {
    int vlanId;
    bool status;
    bool operator==(const vlan& rhs) const {
        return (vlanId == rhs.vlanId) && (status == rhs.status);
    }
};

此外,正如评论中所指出的那样,您应该包含#include <algorithm>(用于定义std::find); 一些编译器可能会隐式地从其他头文件中包含它,但不要依赖这一点。
请注意,根据aschepler的评论,如果您有符合C++20(或更高版本)标准的编译器,您可以将operator==定义为默认值,用于您的vlan类。
struct vlan {
    int vlanId;
    bool status;
    bool operator==(const vlan& rhs) const = default; // C++20
};

对于您的vlan结构体,这将执行与上面定义的“显式”版本完全相同的比较。来自cppreference(或Draft C ++ 20标准本身):

默认等式比较

一个类可以将operator==定义为默认值,返回值为bool。这将生成每个基类和成员子对象的等式比较,按它们的声明顺序。如果两个对象的基类和成员的值相等,则它们是相等的。如果在声明顺序中早期发现成员或基类不相等,则测试会短路。


3
如果您不提供==运算符,那么std::find算法就不会“知道”如何比较两个vlan对象。内置类型有预定义的比较方式;而您定义的类和结构体没有这些。 - Adrian Mole
1
@MinhPham C++ 不知道如何判断你的结构体“相等”——只有你知道。你有两个成员变量,vLanIdstatus。如果 C++ 自己决定什么使你的结构体相等,也许它会只使用其中一个成员并进行比较。因此,C++ 退让了,不能自行决定什么使它们相等。因此,你需要编写代码告诉 C++ 什么使结构体相等,这就是为什么你需要重载 == - PaulMcKenzie
3
如果使用C++20模式,您可以将上述内容缩短为bool operator==(const vlan& rhs) const = default;。(定义一个宇宙飞船操作符也会定义 operator!=, operator<, operator>, operator<=, operator>=,但这些你可能需要也可能不需要。) - aschepler
1
@aschepler 很好的观察。如果我把它融入我的答案中,你会反对吗?(我不想单方面“抢走你的风头!”) - Adrian Mole
2
@AdrianMole 没问题。(所有SE的问题、答案和评论都是CC BY-SA 4.0,如果缺少归属,我很少会抱怨。) - aschepler
显示剩余2条评论

5
在C++中,结构体默认情况下没有生成比较运算符。您需要编写自己的比较运算符:
struct vlan {
    int vlanId;
    bool status;

    bool operator==(const vlan& v) const
    {
        return vlanId == v.vlanId; // or another approach as above
    }
};

3

您还可以使用带有lambda表达式的std::find_if,以便调整为特定查询。或者,如果您只需要快速按ID搜索,则可以使用map。

#include <iostream>
#include <map>
#include <vector>

struct vlan 
{
    size_t vlanId = 0 ;      
    bool status = false;
};

std::vector<vlan> vlanTable;
std::map<size_t, vlan> vlanMap;

bool findInTable(const size_t id)
{
    auto it = std::find_if(vlanTable.begin(), vlanTable.end(), [id](const auto& item) 
    { 
        return item.vlanId == id; // add more checks here
    });

    return (it != vlanTable.end());
}


int main() 
{
    vlan tmp1{ 1,true };

    vlanTable.push_back(tmp1);
    auto found_in_table = findInTable(1);

    vlanMap.insert({ tmp1.vlanId,tmp1 });
    auto found_in_map = (vlanMap.find(1) != vlanMap.end());

    std::cout << "ID 1 ";
    if (!found_in_table) std::cout << "not ";
    std::cout << "found in table" << std::endl;

    std::cout << "ID 1 ";
    if (!found_in_map) std::cout << "not ";
    std::cout << "found in map" << std::endl;

    return 0;
}

谢谢!我尝试了一下,看到它有效。 - Minh Pham

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