Reputation: 2631
When I have a function receiving a (smart) pointer that is supposed to refer something, I always start as follows:
class Foo;
void doSomething(const std::shared_ptr<Foo>& pFoo)
{
assert(pFoo);
// ...
}
Now I am looking for a similar assert condition for a vector (or other container) of (smart) pointers. The best I could come up with is:
void doSomething(const std::vector<std::shared_ptr<Foo> >& pFoos)
{
assert(std::all_of(pFoos.begin(), pFoos.end(), [](const std::shared_ptr<Foo>& pFoo) { return pFoo; }));
// ...
}
I wonder whether this could be improved.. can the lambda be avoided? (I tried to use the get() method of shared_ptr but template deduction fails then) Or is there another way to assert for a whole container?
Upvotes: 7
Views: 1424
Reputation: 2796
one more way to do it:
assert(std::find(pFoos.begin(), pFoos.end(), nullptr) == pFoos.end());
Upvotes: 11
Reputation: 63154
Another slightly convoluted way to express it with standard functionality only:
assert(std::none_of(pFoos.begin(), pFoos.end(), std::logical_not<std::shared_ptr<Foo>>{}));
From C++14 onwards, you can use the generic specialization of std::logical_not
:
assert(std::none_of(pFoos.begin(), pFoos.end(), std::logical_not<>{}));
Upvotes: 9
Reputation: 93324
You could use implement your own utility predicate:
struct is_nullptr
{
template <typename T>
bool operator()(T&& x) const noexcept { return x == nullptr; }
};
void doSomething(const std::vector<std::shared_ptr<Foo> >& pFoos)
{
assert(!std::any_of(pFoos.begin(), pFoos.end(), is_nullptr{});
// ...
}
And/or your own "range assertion":
template <typename TContainer, typename TPredicate>
void range_assert(TContainer&& container, TPredicate&& p)
{
for(auto&& x : container)
{
assert(p(x));
}
}
void doSomething(const std::vector<std::shared_ptr<Foo> >& pFoos)
{
range_assert(pFoos, [](const std::shared_ptr<Foo>& x) { return x; });
// ...
}
Upvotes: 1