Consider the following example:
class Foo {
public:
std::vector<Item*> items = { nullptr, new Item(), new Item(), nullptr };
// function to return all non-nullptr items as an iterator
};
int main() {
Foo foo;
for (Item* i : foo.functionToReturnIteratorOverAllNullItems)
// do something
}
Is it possible to create a function inside the class to return the items in a std::vector also residing in the class, but skipping nullptr items? Or any other items for that matter. I am thinking some lambda function usage would make this work but I am not sure how.
Note I want it to be efficient without re-creating any other new vector and return that. Should preferably work in C++11.
You could use boost::adaptors::filtered (or ranges::view::filter):
// pipe version
for (Item* i : foo.items | filtered([](Item* i){return i;})) {
// ...
}
// function version
for (Item* i : filter(foo.items, [](Item* i){return i;})) {
// ...
}
This is one of the easier range adaptors to write yourself if you want a challenge. You just need an iterator type that does something slightly more complicated than forward along ++ for operator++().
But it's probably easier to just use an if statement, no?
for (Item* i : foo.items) {
// either positive
if (i) {
// ...
}
// or negative
if (!i) continue;
// ...
}
Here's an alternative approach using higher-order functions and lambdas that abstracts the filtering logic. It does not require any additional dependency.
template <typename TContainer, typename TF>
auto for_nonnull_items(TContainer&& container, TF f)
{
for(auto&& i : container)
{
if(i == nullptr) continue;
f(i);
}
return f;
}
std::vector<int*> example{/*...*/};
for_nonnull_items(example, [](auto ptr)
{
// do something with `ptr`
});
By calling for_nonnull_items(this->items, /*...*/) inside foo you can achieve a nicer interface:
foo.for_nonnull_items([](auto ptr)
{
// do something with `ptr`
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With