Удаление std :: tuple из списка std :: list - PullRequest
0 голосов
/ 31 марта 2019

У меня есть список кортежей, и мне нужно удалить элементы из списка, что-то вроде этого:

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

ошибка C2678: бинарный '==': не найден оператор, который занимает левую руку операнд типа 'const _Ty' (или нет приемлемого преобразования)

Как удалить элементы кортежа из списка в приведенном выше примере?

EDIT:

Я попробовал следующий метод, он отлично компилируется в отличие от предыдущего примера, но есть утверждение времени выполнения:

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

Выражение: нельзя увеличить значение инициализированного списка итератором

1 Ответ

0 голосов
/ 31 марта 2019

Во-первых, вы не хотите делать это .Удаление элементов из list (или любого контейнера) в середине for на основе диапазона - это рецепт катастрофы, поскольку , скрытый за циклом for, является итераторами , которые будут недействительными, как толькокак элемент удален

Это та же проблема, что и во втором эксперименте с

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

Эта версия может быть исправлена ​​с помощью

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

или

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

Или

tuple_list.clear();

ОК.О том, что пошло не так:

ошибка C2678: двоичный файл '==': не найден оператор, который принимает левый операнд типа 'const _Ty' (или нет приемлемого преобразования)

означает, что одну из частей кортежа нельзя сравнивать на равенство.

struct A
{

};

не имеет оператора равенства.Решение состоит в том, чтобы добавить один.

struct A
{
}; 

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

Полезное дополнительное чтение:

Идиома Erase-Remove может использоваться для решения подобных проблем.

...