简体   繁体   中英

Removing std::tuple from std::list

I have a list of tuples and need to remove elements from the list, something like this:

enum class test
{
    mem1,
    mem2,
    mem3,
    mem4
};

struct A
{

};

int main()
{
    std::list<std::tuple<int, test, A>> tuple_list;

    // fill list with random objects
    for (int i = 0; i < 4; i++)
    {
        tuple_list.push_back(
               std::forward_as_tuple(i, static_cast<test>(i), A()));
    }

    // now remove it
    for (auto& ref : tuple_list)
    {
        tuple_list.remove(ref); // error C2678
    }
    return 0;
}

error C2678: binary '==': no operator found which takes a left-hand operand of type 'const _Ty' (or there is no acceptable conversion)

How do I remove tuple elements from the list in above example?

EDIT:

I tried following method, it compiles just fine unlike previous example but there is runtime assertion:

int main()
{
    list<tuple<int, test, A>> tuple_list;

    for (int i = 0; i < 4; i++)
    {
        tuple_list.push_back(
                std::forward_as_tuple(i, static_cast<test>(i), A()));
    }

    for (auto iter = tuple_list.begin(); iter != tuple_list.end(); iter++)
    {
        tuple_list.erase(iter);
    }
}

Expression: can not increment value initialized list iterator

First off, you don't want to do this . Removing items from a list (or any container) in the middle of a range-based for is a recipe for disaster as hidden behind the for loop are iterators that will be invalidated as soon as the item is removed.

This is the same problem as the second experiment with

for (auto iter = tuple_list.begin(); iter != tuple_list.end(); iter++)
{
    tuple_list.erase(iter); // iter rendered invalid. 
                            // That makes iter++ and iter != tuple_list.end()
                            // totally bogus.
}

This version can be fixed with

for (auto iter = tuple_list.begin(); iter != tuple_list.end(); /* nothing here */)
{
    iter = tuple_list.erase(iter); // iter updated here
}

or a

while (! tuple_list.empty()) 
{
     tuple_list.pop_front();
}

Or

tuple_list.clear();

OK. On to what went wrong:

error C2678: binary '==': no operator found which takes a left-hand operand of type 'const _Ty' (or there is no acceptable conversion)

means that one of the parts of the tuple cannot be compared for equality.

struct A
{

};

has no equality operator. Solution is to add one.

struct A
{
}; 

bool operator==(const A& lhs, const A& rhs)
{ 
    Comparison logic goes here 
}    

Useful additional reading:

The Erase-Remove idiom can be used to solve similar problems.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM