Custom Iterator using boost iterator

时间:2016-03-04 18:04:45

标签: boost iterator c++03 boost-iterators

I've a custom data structure like following:

class Node;

class GraphDM {
public:
    GraphDM();
    // these are to iterate on all items of _faninNodes 
    // like all elements in multimap
    FaninIter  faninBegin(); 
    FaninIter  faninEnd();

    // these are to iterate on all items of _fanoutNodes
    FanoutIter fanoutBegin();
    FanoutIter fanoutEnd();

    // these should work like equal_range of multimap
    std::pair<FaninIter, FaninIter > getFanins (const Node *node_);
    std::pair<FaninIter, FaninIter > getFanouts(const Node *node_);

private:
    typedef std::vector< Node* > NodeList;
    typedef boost::unordered_map< Node*, 
                                  NodeList > Map;

    Map     _faninNodes;
    Map     _fanoutNodes;
};

I need to implement these APIs. How can I implement these using boost iterator library?

Also, I may need to take a Predicate to allow filtering

Some pointer to get started will be very helpful. One clarification: I cannot use c++0x compiler flags as I need to use c++98 only. So, please suggest a solution that doesn't need c++11 or c++03 compiler flag.

Also, if I design an iterator like following (nested in the GraphDM class), I'm essentially exposing details my data-structure. Is there a way to make the iterator to iterate only on the Key's of the map (and not the value)? Then I can return a different type of iterator for the getFanins() and getFanout() which would be iterator from the value list.

   class Iter : public boost::iterator_adaptor< Iter,
                                                 Map::iterator,
                                                 boost::use_default >
    {
    public:
        Iter() : Iter::iterator_adaptor_() {}


    private:
        friend class GraphDM;

        Iter(Map::iterator it)
                : Iter::iterator_adaptor_(it) {}

        friend class boost::iterator_core_access;

    };

1 个答案:

答案 0 :(得分:0)

我认为您的文本中没有要求创建自定义迭代器。您只需从内部地图中键入dedefor。

在这里,我解决了一些问题:

  • 您通常无法将boost::hash<Node>应用于Node const*。如果您没有指定哈希,它将默认为boost::hash<key_type>,这很可能是您想要的。

  • 有一些const正确性问题(equal_range方法采用const指针)。我已将所有内容更正为const-ness的安全默认值。

<强> Live On Coliru

#include <utility>
#include <boost/unordered_map.hpp>
#include <vector>

struct Node {};

class GraphDM {
    typedef std::vector<Node const*> NodeList;
    typedef boost::unordered_map<Node const *, NodeList/*, boost::hash<Node const*>*/ > Id2NodeListMap;

  public:
    typedef Id2NodeListMap::const_iterator FaninIter;
    typedef Id2NodeListMap::const_iterator FanoutIter;

    GraphDM() {}

    FaninIter  faninBegin()  const;
    FaninIter  faninEnd()    const;

    FanoutIter fanoutBegin() const;
    FanoutIter fanoutEnd()   const;

    // these should work like equal_range of multimap
    std::pair<FaninIter, FaninIter> getFanins(Node const *node_) const;
    std::pair<FaninIter, FaninIter> getFanouts(Node const *node_) const;

  private:
    Id2NodeListMap _faninNodes;
    Id2NodeListMap _fanoutNodes;
};

GraphDM::FaninIter  GraphDM::faninBegin() const {
    return _faninNodes.begin();  
}

GraphDM::FaninIter  GraphDM::faninEnd()   const {
    return _faninNodes.end();
}

GraphDM::FanoutIter GraphDM::fanoutBegin() const {
    return _fanoutNodes.begin();
}

GraphDM::FanoutIter GraphDM::fanoutEnd()   const {
    return _fanoutNodes.end();
}

// these should work like equal_range of multimap
std::pair<GraphDM::FaninIter, GraphDM::FaninIter> GraphDM::getFanins(Node const *node_) const {
    return _faninNodes.equal_range(node_);
}
std::pair<GraphDM::FaninIter, GraphDM::FaninIter> GraphDM::getFanouts(Node const *node_) const {
    return _fanoutNodes.equal_range(node_);
}

int main() {
    GraphDM demo;
}