Search code examples
c++iteratorfindstdlist

Add struct in std::list


I have a following struct:

struct data {
    std::string str;
    int num;
    int num2;
    std::string str2
} data1;

I have a std::list<struct data> list;

I want to add struct in std::list, assuming there is no such structure, use std::find_if and lambda function's.

std::list<data>::iterator it = std::find(list.begin(), list.end(), data1);
if (it == list.end()) list.push_back(data1)

How can you do this?


Solution

  • To use std::find_if and a lambda:

    std::list<data>::iterator it = std::find_if(list.begin(), list.end(),
        [&data1](const data& rhs) {
            return
                data1.str == rhs.str &&
                data1.num == rhs.num &&
                data1.num2 == rhs.num2 &&
                data1.str2 == rhs.str2;
        }
    );
    

    In this case I would however recommend defining data::operator== and using std::find instead:

    struct data {
        std::string str;
        int num;
        int num2;
        std::string str2;
    
        bool operator==(const data& rhs) const {
            return
                str == rhs.str &&
                num == rhs.num &&
                num2 == rhs.num2 &&
                str2 == rhs.str2;
        }
    };
    
    std::list<data>::iterator it = std::find(list.begin(), list.end(), data1);
    

    in C++20, you can simplify this by defaulting operator<=> (the spaceship operator):

    a defaulted <=> overload will also allow the type to be compared with <, <=, >, and >=. If operator<=> is defaulted and operator== is not declared at all, then operator== is implicitly defaulted.

    Given that, here's how to allow data to be compared using all those operators:

    struct data {
        std::string str;
        int num;
        int num2;
        std::string str2;
    
        friend auto operator<=>(const data&, const data&) = default;
    };