ivanovIAVDD
ivanovIAVDD

Reputation: 85

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?

Upvotes: 1

Views: 1452

Answers (3)

anastaciu
anastaciu

Reputation: 23802

You can iterate the list and compare the object you want to add with existing objects, you do it by comparing all data memebers, if they match then the objects are equal. I would advise the implementation a custom comparison operator, instead of comparing data members every time you need to compare objects:

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

    bool operator==(const data &d)
    {
        return this->num == d.num && this->str == d.str && this->num2 == d.num2 && d.str2 == this->str2;
    }
};

For usage with lambda and std::find_if():

data d{"string1", 2, 2, "string2"}; 

std::list<data>::iterator it = std::find_if(list.begin(), list.end(), [&](const data& dt) {
    return d == dt;         
});

if(it == list.end())
{
    list.push_back(d);
}

Note that, as @Remy pointed out in the comment section, this can be more easily achieved using std::find() instead of std::find_if():

std::find(list.begin(), list.end(), d); // comparator implementation also needed

Upvotes: 2

Ted Lyngmo
Ted Lyngmo

Reputation: 117308

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

Upvotes: 2

Adrian Costin
Adrian Costin

Reputation: 438

You did not declare the std::list properly. Make sure to only specify the data type. In this case, the declaration should have been std::list<data> list;.

Afterwards you can create objects of type data and store them inside the std::list using push_back.

Upvotes: 0

Related Questions