2017-07-19 234 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