2016-04-24 69 views
3

所以,比如说,我有一个内部有std::list<std::pair<int, std::string>>的类;我怎么能实现这个类的迭代器,以便它迭代这个列表中包含的字符串?如何在容器项目的字段上创建迭代器?

或者,例如,在我的班级中,我有一个向量struct s,其字段为a,bc;我可以创建一个迭代器(也许是继承向量的迭代器吗?不知道),哪个在取消引用时会返回一个std::pair,对应于(b, c)

通过迭代器我的意思是像std::vector的迭代器的东西:我可以通过whatever.begin()得到的东西,并迭代,如上所述,列表中的字符串。

UPD好的,这里有更多我想要的信息。在我的HashMap类中,我有itemsstructs的列表:每个都有一个键,一个值和一个指向它在表中的位置的指针。我需要的是一个迭代器;但不是我可以通过执行items.begin()得到的那个,因为这个迭代器在解除引用时会返回我的结构。我需要一个迭代器,这样我可以在用户调用HashMap.begin()时返回它,并且它应该取消引用对应于(key,value)的std::pair

这应该希望能让我的问题更清楚。

UPD2 这是我struct,如果这能帮助:

template<class KeyType, class ValueType> 
struct node { 
    KeyType key; 
    ValueType value; 
    node** place; 

    node(KeyType key_ = KeyType(), ValueType value_ = ValueType()): key(key_), value(value_) {}; 
}; 
+0

你不能为任意的结构定义。这需要运行时反射,这在C++中是不可用的。您可以为每个具体结构提供您自己的迭代器实现,尽管您需要使用它。可能['std :: tie()'](http://en.cppreference.com/w/cpp/utility/tuple/tie)在这样做时很有用。 –

+0

你想迭代你的列表中的字符串还是其他的东西? – Galik

+0

你应该解释**为什么**你需要这样的迭代器,因为可能有其他的方法。 – Holt

回答

1

一种优雅的方式是使用转化迭代器或转换范围:

#include <iostream> 
#include <list> 
#include <boost/range/adaptor/transformed.hpp> 
#include <boost/iterator/transform_iterator.hpp> 

int main() { 
    std::list<std::pair<int, std::string>> l; 
    auto extractor = [](auto&& elem) { return elem.second; }; 

    // Using a transformed range. 
    for(auto&& v: l | boost::adaptors::transformed(extractor)) 
     std::cout << v << '\n'; 

    // Using transform iterators. 
    for(auto i = boost::make_transform_iterator(l.begin(), extractor), j = boost::make_transform_iterator(l.end(), extractor); i != j; ++i) 
     std::cout << *i << '\n'; 
} 

要使用一个转换迭代器你的容器你可以这样做:

struct MyContianer 
{ 
    std::list<std::pair<int, std::string>> container; 

    static auto constexpr first_extractor = [](auto&& elem) { return elem.second; }; 
    using iterator_first = decltype(boost::make_transform_iterator(container.begin(), first_extractor)); 
    iterator_first begin_first() { return {container.begin(), first_extractor}; } 
    iterator_first end_first() { return {container.end(), first_extractor}; } 

    static auto constexpr second_extractor = [](auto&& elem) { return elem.second; }; 
    using iterator_second = decltype(boost::make_transform_iterator(container.begin(), second_extractor)); 
    iterator_second begin_second() { return {container.begin(), second_extractor}; } 
    iterator_second end_second() { return {container.end(), second_extractor}; } 

}; 
decltype(MyContianer::first_extractor) constexpr MyContianer::first_extractor; 
decltype(MyContianer::second_extractor) constexpr MyContianer::second_extractor; 

int main() { 
    MyContianer c; 
    c.begin_first(); 
    c.begin_second(); 
} 
+0

嗯,我很确定我不被允许使用'boost'等等,所以...虽然这很棒,但这并不能帮助我 – Akiiino

+0

@Akiiino If你不能重用boost,你可以重用底层思想:为你的容器创建一个迭代器类模板,一个模板参数是transform函数/提取器对象类型。 –