Finding a struct in a vector

Viewed 106

I want to find a struct whose all member data match certain values.

I made a following short program:

#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;
}

It returns error as: template argument deduction/substitution failed right at the find function.

Could someone help me?

3 Answers

You need to provide the == operator for your vlan class:

struct vlan {
    int vlanId;
    bool status;
    bool operator==(const vlan& rhs) const {
        return (vlanId == rhs.vlanId) && (status == rhs.status);
    }
};

Also, as noted in the comments, you should #include <algorithm> (for the definition of std::find); some compilers may implicitly include this from other headers, but don't rely on that.


Note that, as per the comment made by aschepler, if you have a compiler that conforms to the C++20 (or later) Standard, you can define the operator== for your vlan class as defaulted:

struct vlan {
    int vlanId;
    bool status;
    bool operator==(const vlan& rhs) const = default; // C++20
};

For your vlan struct, this will perform the exact same comparison(s) as the 'explicit' version defined above. From cppreference (or the Draft C++20 Standard itself):

Defaulted equality comparison

A class can define operator== as defaulted, with a return value of bool. This will generate an equality comparison of each base class and member subobject, in their declaration order. Two objects are equal if the values of their base classes and members are equal. The test will short-circuit if an inequality is found in members or base classes earlier in declaration order.

In C++, structs do not have a comparison operator generated by default. You need to write your own:

struct vlan {
    int vlanId;
    bool status;

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

You can also use std::find_if with a lambda you can tune for a specific query. Or you if you only need to search by id quickly then you can also use a 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;
}
Related