libzypp: Filter functors operating on ResObjects.

libzypp 17.38.15

Filter functors operating on ResObjects.
Filters and Functors

A simple filter is a function or functor matching the signature:

A simple filter is a function or functor matching the signature:

bool simplefilter( ResObject::Ptr );
zypp::ResObject::Ptr
TraitsType::PtrType Ptr
Definition ResObject.h:42

Note
  It's not neccessary that your function or functor actually returns `bool`. Anything which is convertible into a `bool` will do;

Besides basic filter functors which actually evaluate the `ResObject` (e.g. ByKind, ByName) you may use Functors for building compex queries. to build more complex filters.

// some 'action' functor, printing and counting
// ResObjects.
struct PrintAndCount
{
PrintAndCount( unsigned & counter_r )
: _counter( counter_r )
{}
bool operator()( ResObject::Ptr p ) const
{
DBG << *p << endl;
++_counter;
return true;
}
unsigned & _counter;
};
ResStore store;
unsigned counter = 0;
// print and count all resolvables
store.forEach( PrintAndCount(counter) );
// print and count all resolvables named "kernel"
counter = 0;
store.forEach( ByName("kernel"), PrintAndCount(counter) );
// print and count all Packages named "kernel"
counter = 0;
store.forEach( chain( ByKind(ResKind::package),
ByName("kernel") ),
PrintAndCount(counter) );
// print and count all Packages not named "kernel"
counter = 0;
store.forEach( chain( ByKind(ResKind::package),
not_c(ByName("kernel")) ),
PrintAndCount(counter) );
// same as above ;)
counter = 0;
store.forEach( chain( ByKind(ResKind::package),
chain( not_c(ByName("kernel")),
PrintAndCount(counter) ) ),
true_c() );
DBG
#define DBG
Definition Logger.h:129
zypp::ResKind::package
static const ResKind package
Definition ResKind.h:40
zypp::functor::not_c
Not< TCondition > not_c(TCondition cond_r)
Convenience function for creating a Not from TCondition.
Definition Functional.h:127
zypp::functor::chain
Chain< TACondition, TBCondition > chain(TACondition conda_r, TBCondition condb_r)
Convenience function for creating a Chain from two conditions conda_r and condb_r.
Definition Functional.h:185
zypp::functor::true_c
True true_c()
Convenience function for creating a True.
Definition Functional.h:89
zypp::resfilter::ByName::ByName
ByName()
Definition ResFilters.h:153

As you can see in the last example there is no difference in using a filter or an action functor, as both have the same signature. A difference of course is the way forEach interprets the returned value.

Consequently you can netgate and chain actions as well. Thus PrintAndCount(counter) could be chain(Print(),Count(counter)), if these functors are provided.

Note
  These functors are not limited to be used with ResStore::forEach. You can use them with std::algorithms as well.

`PrintAndCount` is an example how a functor can return data collected during the query. You ca easily write a collector, that takes a std:list<ResObject::Ptr>& and fills it with the matches found.

But as a rule of thumb, a functor should be lightweight. If you want to get data out, pass references to variables in (and assert these variables live as long as the query lasts). Or use std::ref.

Internally all functors are passed by value. Thus it would not help you to create an instance of some collecting functor, and pass it to the query. The query will then fill a copy of your functor, you won't get the data back. (Well, you probabely could, by using boosr::ref).

Why functors and not plain functions?

You can use plain functions if they don't have to deliver data back to the application. The `C-style` approach is having functions that take a void * data as last argument. This `data` pointer is then passed arround and casted up and down.

If you look at a functor, you'll see that it contains both, the function to call (its operator()) and the data you'd otherwise pass as void * data. That's nice and safe.

Todo
  migrate to namespace filter and enhance to support Solvables as well.