[ptr_list] erase_if issue - bug or feature?
Hi all. There is an issue found with erase_if algorithm for ptr_list container. Here is a bit of code: class A; boost::ptr_list<A> m_sheeps; class A { public: A(int i) : m_i(i) {} operator int () { return this->m_i; } void mydelete (int i) { m_sheeps.erase_if(std::bind2nd(std::less<int>(), i)); } public: int m_i; }; ////////////////////////////////////////////////////////////////////////// int main() { m_sheeps.push_back(new A(1)); m_sheeps.push_back(new A(3)); m_sheeps.push_back(new A(4)); for (boost::ptr_list<A>::iterator iter = m_sheeps.begin(); iter != m_sheeps.end();) { std::cout << (*iter).m_i; (*iter++).mydelete(2); } return 0; } This code outputs following sequence to the console: 14 This sequence does not contains '3' because of erase_if modify underlaying list container with stable_partition algorithm also. If I replace boost::ptr_list to std::list the output will correct (i. e. '134') Main question is following: is such behavior correct for certain kind of container? I suspect what ptr-containers preserve standard semantic of corresponded standard containers. And erasing from the ptr_list does not invalidate iterators to this list (exclude cases described in the Standard). Or ptr_list::erase_if algorithm does not preserve semantic of ptr_list::remove_if algorithm? But there is nothing about such behavior in the documentation. PS: I know what erase_if algorithm has generic implementation (in the ptr_sequence class) and has not special implementation for ptr_list. But documentation has the following sentence: " Iterators are invalidated as in the corresponding standard container Because the containers in this library wrap standard containers, the rules for invalidation of iterators are the same as the rules of the corresponding standard container. For example, for both boost::ptr_vector<T> and std::vector<U> insertion and deletion only invalidates the deleted element and elements following it; all elements before the inserted/deleted element remain valid. " (http://www.boost.org/doc/libs/1_35_0/libs/ptr_container/doc/conventions.html#iterators-are-invalidated-as-in-the-corresponding-standard-container) -- Best Regards Sergey mailto:flex_ferrum@artberg.ru
Sergey Sadovnikov skrev:
Hi all.
There is an issue found with erase_if algorithm for ptr_list container. Here is a bit of code:
The code in trunk changed after we could patch the release branch. Could you please check that code to see if it is still surprising to you? Thanks -Thorsten
Hello, Thorsten.
Monday, May 5, 2008 at 10:30:21 PM you wrote:
TO> Sergey Sadovnikov skrev:
TO> The code in trunk changed after we could patch the release branch. Could
TO> you please check that code to see if it is still surprising to you?
Trunk code is still surprising me. :) If boost::ptr_sequence_adapter::erase_if has to guarantee
standard std::list::remove_if behavior (for ptr_list container, of
course) it should be overridden in the ptr_list
class. For example, in this way:
template
<
class T,
class CloneAllocator = heap_clone_allocator,
class Allocator = std::allocator
Sergey Sadovnikov skrev:
Hello, Thorsten.
Monday, May 5, 2008 at 10:30:21 PM you wrote:
TO> Sergey Sadovnikov skrev:
TO> The code in trunk changed after we could patch the release branch. Could TO> you please check that code to see if it is still surprising to you? Trunk code is still surprising me. :) If boost::ptr_sequence_adapter::erase_if has to guarantee standard std::list::remove_if behavior (for ptr_list container, of course) it should be overridden in the ptr_list class. For example, in this way:
template < class T, class CloneAllocator = heap_clone_allocator, class Allocator = std::allocator
> class ptr_list /* ... */ { public: //... template< class Pred > void erase_if( Pred pred ) { this->base().remove_if(void_ptr_delete_if (pred)); } //... }; This code corresponds all my expectations. :)
I think we need to classify this as a bug for ptr_list. I'll add the above to that class. Thanks -Thorsten
participants (2)
-
Sergey Sadovnikov
-
Thorsten Ottosen