C ++, how to assert that all std :: shared_ptr in a vector refer to something

When I have a function that receives a (smart) pointer that needs to pass something, I always start the following:

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 was:

 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 if this can be improved. Can lambda be avoided? (I tried using the get () method of shared_ptr, but the template deduction failed) Or is there another way to approve for the entire container?

+6
source share
3 answers

another way to do this:

 assert(std::find(pFoos.begin(), pFoos.end(), nullptr) == pFoos.end()); 
+9
source

Another slightly confusing way to express it only with standard functions:

 assert(std::none_of(pFoos.begin(), pFoos.end(), std::logical_not<std::shared_ptr<Foo>>{})); 

Starting with C ++ 14, you can use the general specialization std::logical_not :

 assert(std::none_of(pFoos.begin(), pFoos.end(), std::logical_not<>{})); 
+8
source

You can use 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 statement”:

 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; }); // ... } 
+1
source

Source: https://habr.com/ru/post/1260987/


All Articles