Как стереть & quot; это & ​​quot; от boost :: ptr_vector

У меня есть boost :: ptr_vector, содержащий указатели на класс «holdable».

boost::ptr_vector<holdable> items;

Я добавляю новые элементы в этот вектор из удерживаемого класса следующим образом:

currentplanet->items.push_back(this);

где currentplanet — указатель на объект класса, содержащего ptr_vector. Это все хорошо.

Что меня смущает, так это как удалить запись из ptr_vector из функции в своем собственном классе. Я пытаюсь:

currentplanet->items.erase(std::find(currentplanet->items.begin(),
currentplanet->items.end(),
this));

как в соответствии с ответом на аналогичный вопрос здесь: Как стереть элементы из boost :: ptr_vector, но я явно где-то ошибся, вероятно, в отношении использования «этого».

При попытке компиляции я получаю сообщение об ошибке от stl_algo.h

stl_algo.h|174|error: no match for 'operator==' in '__first.boost::void_ptr_iterator<VoidIter, T>::operator*
[with VoidIter = __gnu_cxx::__normal_iterator<void**, std::vector<void*, std::allocator<void*> > >,
T = holdable]() == __val'|

Я уверен, что это что-то очевидное, но меня, вероятно, смущает косвенность ptr_vector … спасибо за любые ответы заранее!

1

Решение

Как написали другие — это правда, что ptr_vector вступает во владение вашим объектом, но если вы настаиваете на возможности удаления объекта из ptr_vector само по себе — используйте find_if, а не find:

Holdable* ptr = this;
currentplanet->items.erase(std::find_if(currentplanet->items.begin(),
currentplanet->items.end(),
[ptr](const Holdable& other)
{return ptr == &other;} ));

Обратите внимание, что find используется с *this может найти другой объект, который равен *this


Для компиляторов, все еще не поддерживающих лямбда-выражения (эта вещь начинается с [ptr]), используйте свой собственный предикат:

struct CompareToPtr {
CompareToPtr(Holdable* ptr) : ptr(ptr) {}
bool operator () (const Holdable& other) const { return &other == ptr; }
Holdable* ptr;
};
currentplanet->items.erase(std::find_if(currentplanet->items.begin(),
currentplanet->items.end(),
CompareToPtr(this)));
2

Другие решения

Я понял, что std :: find требует значения (не указателя) для третьего параметра, поэтому вы передаете диапазон [«begin», «end») для поиска и значение, которое вы ищете

Это то, что вы имели в виду?

currentplanet->items.erase(std::find(currentplanet->items.begin(),
currentplanet->items.end(),
*this));

обратите внимание на * это

2

Альф правильно, но по причине, которая несколько свойственна boost::ptr_vector (и другие связанные boost::reversible_ptr_container контейнеры), который я думаю, должен быть вызван. Обычно итератор элемента контейнера разыменовывает ссылку на контейнер value_type,

boost:ptr_vector<T>::value_type является typedef для T*; Однако разыменование boost::ptr_vector<T>::iterator не приводит к T* ссылка.

Из ускоренной документации (http://www.boost.org/doc/libs/1_52_0/libs/ptr_container/doc/reversible_ptr_container.html):

Также обратите внимание, что

typedef ... iterator

позволяет перебирать T& объекты, а не Т *.

Разыменование boost::ptr_vector<T>::iterator приводит к T&, Вот почему вас смущает косвенность ptr_vector, и именно поэтому последний аргумент std::find() должен быть holdable объект, а не holdable*,

Наконец, обратите внимание, что комментарий Xeo о ptr_vector следует понимать владение указателями — это может иметь смысл в очень ограниченных ситуациях, когда объект хочет удалить себя, но вы должны делать это с полным пониманием того, что после этого erase() звоните, вы ничего не можете сделать с объектом. Если это не то поведение, которое вам нужно, вместо erase() Вы можете рассмотреть возможность использования release(), который освободит контейнер от владения указателем и удалит его из контейнера (чтобы объект не был уничтожен).

2
По вопросам рекламы [email protected]