2016-12-08 54 views
5

當我有一個函數接收應該參照的東西(智能)指針,我總是開始如下:C++如何斷言,所有的std :: 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; })); 
    // ... 
} 

我不知道這是否可以改善.. lambda可以避免嗎? (我嘗試使用shared_ptr的get()方法,但模板演繹失敗)或者是否有另一種方法來聲明整個容器?

+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

相關問題