2016-12-08 1 views
5

Когда у меня есть функция, получающее (смарт) указатель, который должен передать что-то, я всегда начинаю следующим образом:C++, как утверждать, что все станд :: shared_ptr в векторе, ссылаясь на то

class Foo; 
void doSomething(const std::shared_ptr<Foo>& pFoo) 
{ 
    assert(pFoo); 
    // ... 
} 

Теперь я ищу аналогичное условие утверждения для вектора (или другого контейнера) (умных) указателей. Самое лучшее, что я мог придумать, это:

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

Интересно, может ли это быть улучшено. Можно ли избежать лямбда? (Я попытался использовать метод get() для shared_ptr, но вычет шаблона не удался) Или существует другой способ для утверждения для всего контейнера?

+2

Есть ли причина, почему вы не измените вашу функцию синтаксис для получения «Foo &» вместо? В конце концов, это _guarantees_ есть объект и не требуется утверждение. Аналогично вектору, который может содержать 'std :: reference_wrapper '. – paddy

+5

'assert (! Std :: count (v.begin(), v.end(), nullptr));' –

+1

@PiotrSkotnicki Это посещает все элементы, тогда как мы можем вырваться, когда первый, который не удовлетворяет условие найдено. – juanchopanza

ответ

8

еще один вариант, чтобы сделать это:

assert(std::find(pFoos.begin(), pFoos.end(), nullptr) == pFoos.end()); 
1

Вы можете использовать реализовать собственную утилиту предиката:

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{}); 
    // ... 
} 

и/или свой собственный «диапазон утверждение»:

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

Еще немного запутанный способ выразить его со стандартной функциональностью только:

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

С C++ 14 года, вы можете использовать общую специализацию std::logical_not:

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

это решение работает только для C++ 14, и оно не работает для C++ 11 – Sandro

+0

@Sandro спасибо за хедз-ап, исправлено Это. – Quentin

Смежные вопросы