2016-12-08 6 views
5

Kiedy mam funkcję odbiera (Smart) wskaźnik, który ma odnosić się coś, zawsze zaczynają się następująco:C++ jak twierdzić, że wszystko std :: shared_ptr w wektorze odnosimy się do czegoś

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

Teraz szukam podobnego warunku asertywnego dla wektora (lub innego pojemnika) wskaźników (inteligentnych). Najlepsze co mogę wymyślić to:

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

Zastanawiam się, czy można to poprawić. Czy można uniknąć lambda? (Próbowałem użyć metody get() shared_ptr, ale odliczanie szablonów nie powiedzie się). Czy istnieje inny sposób potwierdzenia całego kontenera?

+2

Czy jest jakiś powód, dla którego nie zmieni swoją funkcję na Składnia do otrzymania 'Foo &' zamiast? Wszakże to _warunki_ są obiektem i nie wymaga się dowodu. Podobnie jest z wektorem, który może zawierać 'std :: reference_wrapper '. – paddy

+5

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

+1

@PiotrSkotnicki Który odwiedza wszystkie elementy, podczas gdy możemy wyjść, gdy pierwszy, który nie spełnia znaleziono warunek. – juanchopanza

Odpowiedz

8

jeszcze jeden wariant, aby to zrobić:

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

Można użyć zaimplementować własną orzecznik użytkowy:

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

i/lub własne „zakres twierdzenie”:

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

Innym nieco pokrętnym sposobem wyrażania go ze standardową funkcjonalnością tylko:

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

Od C++ 14 roku, można użyć rodzajowego specjalizację std::logical_not:

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

to rozwiązanie działa tylko dla C++ 14 i nie działa dla C++ 11 – Sandro

+0

@Sandro dzięki za heads-up, naprawione to. – Quentin

Powiązane problemy