2016-08-02 68 views
5

有各種STL算法依賴輸出迭代器來存儲算法的結果。輸出迭代器適配器進行計數但不復制

例如,std::set_intersection將在輸出迭代器中存儲兩個排序範圍之間的所有公共元素,然後每輸出一個元素後遞增。

有時,我對實際元素不感興趣,但只對輸出元素的數量感興趣。在這種情況下,複製元素會浪費內存和性能。有沒有可以用來計算和避免元素副本的迭代器適配器?如果不是,你能建議這樣一個適配器的通用實現嗎?

+0

投票關閉作爲資源的請求,但是您可能希望['提振:: counting_iterator'(http://www.boost.org/doc/libs/1_50_0/libs/iterator/doc/counting_iterator。 html) – NathanOliver

+0

你的問題有點不清楚:你想知道有多少個元素將包含2個交集而沒有計算交集? – wasthishelpful

+0

@wasthishelpful是的,在我的set_difference示例中,但我正在尋找一種適用於任何此類算法的通用Ouput迭代器解決方案。 – T33C

回答

0

由於很多從@ecatmur回答和評論的幫助下,我有以下的解決方案,我邀請評論。我曾希望得到boost::make_function_output_iterator工作,但似乎有一個庫中的錯誤,無法定義賦值運算符。

#include <algorithm> 
#include <vector> 
#include <iostream> 
#include <string> 
#include <cassert> 

class counting_output_iterator 
{ 
public: 
    counting_output_iterator& operator=(const counting_output_iterator&) { return *this; }; 
    explicit counting_output_iterator(std::size_t& count) : m_count(count) {} 
    template<typename T> void operator=(const T&) {}; //NULL op 
    using iterator_category = std::output_iterator_tag; 
    using value_type = void; 
    using difference_type = void; 
    using pointer = void; 
    using reference = void;  
    counting_output_iterator& operator*() { return *this; } 
    counting_output_iterator& operator++() { ++m_count; return *this; } 
    std::size_t& m_count; 
}; 

int main(int, char*[]) 
{ 
    std::vector<int> arr{ 1,2,3,4 }; 
    std::size_t count = 0; 
    std::copy(std::begin(arr), std::end(arr), counting_output_iterator{ count }); 
    assert(count == 4u); 
    return 0; 
} 
4

Boost的Function Output Iterator可以做你想做什麼:

std::size_t count = 0u; 
int arr[]{0, 1, 2, 3}; 
std::copy(std::begin(arr), std::end(arr), 
    boost::make_function_output_iterator([&](auto const&) { ++count; })); 
assert(count == 4u); 

唯一的問題是,你必須聲明迭代器外的計數變量,因爲沒有辦法來提取一個boost::function_output_iterator存儲函數對象(和也沒有辦法從lambda中提取閉包值,即使你超過了這個障礙)。如果你希望能夠編寫單行程序,你必須自己編寫迭代器類,但它不是大量的代碼;例如:

class counting_output_iterator { 
public: 
    using iterator_category = std::output_iterator_tag; 
    using value_type = void; 
    using difference_type = void; 
    using pointer = void; 
    using reference = void; 

    std::size_t value = 0u; 

    struct output_proxy { 
    output_proxy(std::size_t& value) : m_value(value) { } 
    template<class T> output_proxy& operator=(T const&) { 
     ++m_value; 
     return *this; 
    } 
    std::size_t& m_value; 
    }; 
    output_proxy operator*() { return output_proxy(value); } 
    counting_output_iterator& operator++() { return *this; } 
    counting_output_iterator& operator++(int) { return *this; } 
}; 

用法:

int arr[]{0, 1, 2, 3}; 
auto const count = std::copy(std::begin(arr), std::end(arr), 
    counting_output_iterator{}).value; 
assert(count == 4u); 
+0

看起來很有前途,但代碼不能在VS2015U2中使用Boost 1.59進行編譯。嘗試引用已刪除的功能。我換成了一個函數,編譯但計算6而不是3。奇怪!我仍在調查。感謝您的建議。 – T33C

+0

你已經做了大量的編輯,因爲我評論過,所以首先嚐試這些可能會使我的評論無效。謝謝你的幫助。 – T33C

+0

Lambda解決方案仍然失敗。 counting_output_operator的工作原理依賴於返回輸出迭代器的算法,否則該值無法訪問。你已經把我放在正確的軌道上,我會做更多的嘗試。 – T33C