2017-07-19 237 views
1

我有一個任務,我必須計算有多少種不同類型的對象,並保存結果以便稍後從中創建圖形。我正在做的是創建存儲滿足不同條件的元素的排序向量,並在其上調用std::set_intersection來查找它們中有多少滿足複合語句。例如:STL中是否有默認的計數器對象

// Count round and black objects 
std::vector<SomeObject*> roundAndBlackObjects; 
std::set_intersection(roundObjects.begin(), roundObjects.end(), 
    blackObjects.begin(), blackObjects.end(), 
    std::back_inserter(roundAndBlackObjects)); 
std::size_t numRoundAndBlackObjects = roundAndBlackObjects.size(); 

雖然這似乎太複雜了。畢竟,我只想計算共同的元素。有沒有辦法省略不必要的矢量push_backs?是否有捷徑可尋?就像輸出迭代器生成器一樣,它創建一個不構造任何東西的虛擬輸出迭代器,只是對其增量的調用進行計數。這樣,我可以做這樣的事情:

// Count round and black objects 
std::size_t numRoundAndBlackObjects = 0; 
std::set_intersection(roundObjects.begin(), roundObjects.end(), 
    blackObjects.begin(), blackObjects.end(), 
    std::iterator_callback_counter<SomeObject*>(numRoundAndBlackObjects)); 

如果沒有這樣的事情,有一個簡單的方法來創建這樣的元對象?

+0

你能否解釋一下什麼是太複雜?在我看來,你想要做的是一組交集的教科書示例。我也不明白你問題的標題是什麼意思。 –

+2

Boost有[counting_iterator](http://www.boost.org/doc/libs/1_50_0/libs/iterator/doc/counting_iterator.html)。 – Jarod42

+1

如果你想建立一個直方圖,一個'std :: map'確實很好地工作,只需要線性遍歷數據集來填充它。 – NathanOliver

回答

2

你可以差不多使用普通int

std::set_intersection調用輸出迭代器上的兩個運算符,一元運算符operator*operator++。在int上調用後者是您的計數方式,但您需要一個包裝來忽略operator*

你如何忽略operator*?它必須返回允許*iter = value的東西。那麼,你的包裝可能會返回*this。這意味着operator=也會在你的包裝上被調用。這又可以返回*this

所以,把它放在一起:

class counter { 
    size_t count = 0; // Let's count a bit further 
public: 
    counter& operator++() { ++count; return *this; } // ++X 
    counter& operator++(int) { ++count; return *this; } // X++ 
    counter& operator*() { return *this; } 
    template<typename T> counter& operator=(T&&) { return *this; } 
    counter& operator=(counter&) = default; // Don't break normal assignment. 

    operator size_t() const { return count; } 
}; 
+0

Sugoi!這是我一直在尋找的,謝謝。 :) –

+0

爲什麼要改變?第一個代碼有問題嗎? –

+0

@AdamHunyadi:我添加了'operator ++(int)'來允許'myCounter ++'。 – MSalters