2016-11-29 71 views
3

我正在嘗試編寫一個迭代器適配器,每次它被解引用時都應調用成員函數(或訪問對象的成員)。這裏有一個這樣的API的例子:迭代器適配器,在解除引用時調用成員函數

vector<pair<int,int>> ps = {{1,"a"}, {2,"b"}, {3,"c"}}; 

// Pairs that represent ranges 
auto rf = make_adaptor(ps.begin(), ps.end(), [](const auto& x) {return x.first;} 
auto rs = make_adaptor(ps.begin(), ps.end(), [](auto& x) {return x.second;} 

應該打印出來123

for_each(rf.first, rf.second, [](const auto& x){std::cout << x;}); 

如若對每second元素設置在ps

for_each(rs.first, rs.second, [](auto& x){ x = "hello";}); 

我曾嘗試寫作自己iterator鍵入一個make_adaptor方法,但我似乎無法得到它的工作:

template <typename Iterator, typename UnaryOp> 
struct adaptor { 
    using value_type = std::result_of<UnaryOp(typename Iterator::reference)>::type; 
    using reference = value_type&; 
    using pointer = value_type*; 
    using difference_type = typename Iterator::difference_type; 
    using iterator_category = typename Iterator::iterator_category; 

    adaptor(){}; 
    adaptor(Iterator it, UnaryOp func) : _it(it), _func(func) {} 

    reference operator*() const { return _func(*_it); } 
    pointer operator->() const { return &_func(*_it); } 

    bool operator==(const adaptor& other) const { return _it == other._it; } 
    bool operator!=(const adaptor& other) const { return _it != other._it; } 

    adaptor& operator++() { 
     ++_it; 
     return *this; 
    } 

    Iterator _it; 
    UnaryOp _func; 
}; 



template <typename Iterator, typename UnaryOp> 
    auto make_adaptor(Iterator first, Iterator last, UnaryOp func) { 
     return std::make_pair(adaptor<Iterator, UnaryOp>(first, func), 
           adaptor<Iterator, UnaryOp>(last, func)); 
    }; 

這樣做的原因是:比方說,我有一個算法convex_hull其上points工作。但是現在我有一個包含points作爲成員的對象(struct A { points pos;};)。我想在A的集合上致電convex_hull

+1

注:臨時'操作符 - >'被返回的地址以及'運營商*'將返回晃來晃去參考。 – Zereges

+0

這是我提出的問題之一,不幸的是我不知道如何以通用的方式解決這些問題。 – fuji

+0

我肯定會緩存函數調用的結果,因爲您可能不希望在迭代器每次取消引用時計算'func'。然後你可以返回cahced變量(或者它的地址)和註釋,*遞增適配器將使其失效。* – Zereges

回答

0

隨着range-v3,你可以做類似的東西:

const std::vector<std::pair<int,const char*>> ps = {{1,"a"}, {2,"b"}, {3,"c"}}; 

for (const auto s : ps | ranges::view::keys) 
{ 
    std::cout << " " << s; 
} 

for (const auto s : ps | ranges::view::transform([](const auto& p) { return p.first;})) 
{ 
    std::cout << " " << s; 
} 

Demo

相關問題