tags:

views:

42

answers:

2

There is a simple POD data type like

struct Item {
   int value1;
   double value2;
   bool value3;
}

Now I would like to write different count functions like it could be done with the following code (or some std method):

typedef bool Selector(const Item& i);
int count(const vector<Item>& items, Selector f) {
  int sum = 0;
  BOOST_FOREACH(const Item& i, items) {
    if(f(i)) {
      sum++;
    }
  }
  return sum;
}

with f e.g.

bool someSimpleSelector(const Item& i) {
  return i.value1 > 0; // quite simple criterion
}

However in this approach the compiler can not inline the function call and thus will not inline my (trivial) selection code.

My question would be: is there a possibility to implement the above code in a way, where the compiler can inline my selection code, but without implementing the whole count function again and again explicitely (for example by using templates)?

+1  A: 

See the new boost range adaptors

Selector f;
int count = std::distance(items | boost::range::adaptor::filtered(f));

For more details read on. http://www.boost.org/doc/libs/1_43_0/libs/range/doc/html/range/reference/adaptors/reference/filtered.html

bradgonesurfing
Does this create a new sequence or is it implemented lazy?
Danvil
The range adapters are totally lazy and they compose very nicely. I now use them exclusively for range processing algorithms. The one other element of the toolkit not provided by boost is polymorphic iterators / ranges. Read here if you are curious. http://www.artima.com/cppsource/type_erasure.html
bradgonesurfing
This looks interesting and is probably worth getting into it. But for now I choosed the simpler approach in the other answer.
Danvil
Actually *most* of the time you can avoid creating struct type functions and just use normal C functions together with boost::bind. Or if you are brave enough to use c++0x features in GCC you can use lambdas.std::distance(items | filtered( [ } )) Then you will almost be able to program C++ like Ruby!
bradgonesurfing
+1  A: 

Replace the typedef with a template parameter, to allow generic functors:

template <typename Selector>
int count(const vector<Item>& items, const Selector &f)

Then replace your functions with function objects:

struct someSimpleSelector
{
    bool operator()(const Item& i) const { return i.value1 > 0; }
};

You should find that this gets inlined, with suitable compiler optimisation settings.

By the way, this particular problem can be solved using std::count_if().

Mike Seymour