libzypp  13.10.6
Code Snippets

for_

If you prefer using iterator in a for loop, but dislike to figure out the exact type of the iterator, you may find the for_ macro convenient:

#include "zypp/base/Easy.h"
for_( it, pool.byIdentBegin( kind, name ),
pool.byIdentEnd( kind, name ) )
{
PoolItem copy = *it;
}

instead of:

for ( ResPool::byIdent_iterator it = pool.byIdentBegin( kind, name ),
end = pool.byIdentEnd( kind, name );
it != end, ++it )
{
PoolItem copy = *it;
}

erase elements from containers

  // //////////////////////////////////////////////////////////////////////
  // Avoid buggy code, that tries to erase elements, matching a
  // certain property from containers. Example:
  //
  //  for (ResStore::iterator it = store.begin(); it != store.end(); ++it)
  //  {
  //    _pool.erase(*it);
  //  }
  //
  // Problem: Removing an element from a container invalidates (at least)
  //          all iterators pointing to it. Thus after erasing *it, it is
  //          no longer valid. ++it has UNDEFINED BEHAVIOUR.

  // //////////////////////////////////////////////////////////////////////
  // Loop based algorithms (differs depending on the kind of container)
  // =====================
  // //////////////////////////////////////////////////////////////////////

  // //////////////////////////////////////////////////////////////////////
  // Sequential container (vector string deque list): erase returns
  // a valid iterator to the next element.
  // //////////////////////////////////////////////////////////////////////

    SeqContainer c;
    for ( SeqContainer::iterator it = c.begin(); it != c.end(); /**/ )
      {
        if ( toBeRemoved( *it ) )
          {
            it = c.erase( it ); // valid next-iterator returned
          }
        else
          ++it;
      }


  // //////////////////////////////////////////////////////////////////////
  // Associative container (maps sets): erase returns void, but we can use
  // postfix increment, as ONLY iterators to the eased object get invalid:
  // //////////////////////////////////////////////////////////////////////

    AssocContainer c;
    for ( AssocContainer::iterator it = c.begin(); it != c.end(); /**/ )
      {
        if ( toBeRemoved( *it ) )
          {
            c.erase( it++ ); // postfix! Incrementing before erase
          }
        else
          ++it;
      }


  // //////////////////////////////////////////////////////////////////////
  // stl algorithms
  // ==============
  //
  // In case toBeRemoved above is actually a function/functor.
  // //////////////////////////////////////////////////////////////////////


  // //////////////////////////////////////////////////////////////////////
  // Sequential container (vector string deque): stl::remove_if,
  // does not erase elements, they are just moved to the containers
  // end, and an iterator to the 1st item to be 'removed' is returned.
  // //////////////////////////////////////////////////////////////////////

    SeqContainer c;
    c.erase( stl::remove_if( c.begin(), c.end(), toBeRemoved ),
            c.end() );


  // //////////////////////////////////////////////////////////////////////
  // Sequential container (list): The above works too, but list has a
  // builtin remove/remove_if which is more efficient.
  // //////////////////////////////////////////////////////////////////////

    list c;
    c.remove_if( toBeRemoved );


  // //////////////////////////////////////////////////////////////////////
  // Associative container (maps sets): Actually the loop above is the most
  // efficient solution. There is an algorithm based solution, but it requires
  // copying all elements not to be removed ;(
  // //////////////////////////////////////////////////////////////////////

    AssocContainer c;

    AssocContainer keepItems;
    stl::remove_copy_if( c.begin(), c.end(),
                        stl::inserter( keepItems, keepItems.end() ),
                        toBeRemoved );
    c.swap( keepItems );