2014-11-23 71 views
1

考慮下面的代碼:的boost :: any_range和運營商[]

#include <boost/range.hpp> 
#include <boost/range/any_range.hpp> 
#include <boost/range/join.hpp> 

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

struct TestData { 
    TestData() : m_strMem01("test"), m_intMem02(42), m_boolMem03(true) {} 
    std::string m_strMem01; 
    int m_intMem02; 
    bool m_boolMem03; 
}; 

struct IntComp { 
    bool operator()(const TestData &s, int i) { return s.m_intMem02 < i; } 
    bool operator()(int i, const TestData &s) { return i < s.m_intMem02; } 
    bool operator()(const TestData &i, const TestData &s) { 
    return i.m_intMem02 < s.m_intMem02; 
    } 
}; 
struct StrComp { 
    bool operator()(const TestData &s, const std::string &str) { 
    return s.m_strMem01 < str; 
    } 
    bool operator()(const std::string &str, const TestData &s) { 
    return str < s.m_strMem01; 
    } 
    bool operator()(const TestData &i, const TestData &s) { 
    return i.m_strMem01 < s.m_strMem01; 
    } 
}; 

typedef boost::any_range<TestData, boost::forward_traversal_tag, 
         const TestData &, std::ptrdiff_t> TestRange; 

std::vector<TestData> vecData(10); 
std::list<TestData> listData(20); 

TestRange foo() { 
    TestRange retVal; 

    auto tmp1 = std::equal_range(vecData.cbegin(), vecData.cend(), 42, IntComp()); 
    retVal = boost::join(retVal, tmp1); 
    auto tmp2 = 
     std::equal_range(listData.cbegin(), listData.cend(), "test", StrComp()); 
    retVal = boost::join(retVal, tmp2); 
    return retVal; 
} 

int main(int argc, char *argv[]) { 
    auto res = foo(); 
    for (auto a : res) { 
    std::cout << a.m_strMem01 << std::endl; 
    } 
    //std::cout << res[4].m_intMem02 << std::endl; 
} 

如果取消註釋最後一行,因爲distance_to不是any_forward_iterator_interface實現的代碼失敗。我不確定我在這裏錯過了什麼,例如執行operator[]distance_to但是爲了什麼?我自己的版本遍歷標籤?爲什麼它不起作用呢?

Coliru version

回答

2

我想說的答案取決於您的性能需求和你的懶惰,當談到實施新的迭代抽象。 []運算符不工作的核心原因是std :: list < ...>不提供隨機訪問遍歷迭代器。如果你想選擇一個提供這種迭代器的容器。你any_range < ...>可能採取了random_access_traversal_tag,一切都會好起來的。 我認爲這是公平地說,這不是什麼大不了通過簡單地封裝當前索引來實現在列表頂部的隨機訪問迭代器,每當一個特定的位置,就是要訪問的列表中算前進,後退,但這顯然與表現明顯不符。

  • 是否有充分的理由將其中一個集合保存在列表中?
  • 是否有一個很好的理由隨​​機訪問由此產生的any_range?
  • 是否值得提供的std ::列表中的低效的隨機訪問接口的努力?
+0

好點。首先,列表實現解釋了爲什麼沒有運營商[]。根據你的問題。在現實生活中沒有列表或向量,這僅僅是一個例子。在我的情況下,它是Boost MIC,它實際上隱藏了它的實現,並且我不能在任何之上實現operator []。但現在,當我明白'爲什麼'時,我可以進一步觀察MIC,也許我可以在索引中玩耍,以提供隨機訪問。 – kreuzerkrieg 2014-11-23 13:16:23

+0

@ kreuzerkrieg下一次,只要提到你是真的**然後嘗試在問題中實現。當操作符括號被實現時(即'random_access'索引和'unique'索引),Boost MIC非常清楚。當然,你需要的是'random_access'索引。如果你使用它,你的any_range也會有隨機訪問。 – sehe 2014-11-23 13:18:49

+0

燁,最近我過於簡單的例子讓更多的混亂比從混亂節約:( – kreuzerkrieg 2014-11-23 13:21:49

1

當然,any_iterator(它是any_range實現的基礎)不會無償地爲任何通過的奇數迭代器模擬RandomAccess迭代器。

如果你想要的,只要一個迭代器適配器,做這個(使其在列表中隨機存取元素非常緩慢 - 不這樣做)。

+0

我不會:)他們會很樂意生活在沒有它...與否 – kreuzerkrieg 2014-11-23 13:19:36