2016-03-04 3 views
0

Я структура пользовательских данных, как следующее:Пользовательский итератор с помощью наддува итератора

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; 
}; 

Мне нужно реализовать этот API. Как я могу реализовать их с помощью библиотеки итераторов boost?

Кроме того, я, возможно, потребуется принять предиката, чтобы фильтровать

Некоторые указатель, чтобы начать работу, будет очень полезно. Одно уточнение: я не могу использовать флагов компилятора C++ 0x, поскольку мне нужно использовать только C++ 98. Поэтому, пожалуйста, предложите решение, для которого не требуется флаг компилятора C++ 11 или C++ 03.

Кроме того, если я проектирую итератор, как следующий (вложенный в класс GraphDM), я по существу раскрываю детали своей структуры данных. Есть ли способ сделать итератор итерацией только на Ключи карты (а не на значение)? Затем я могу вернуть другой тип итератора для getFanins() и getFanout(), который будет итератором из списка значений.

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; 

    }; 
+0

Одно уточнение: я не могу использовать C++ 0x. Поэтому, пожалуйста, предложите решение, для которого не требуется флаг компилятора C++ 11 или C++ 03. – soumeng78

+0

Это то, что я получаю: вы даже не знаете, какой уровень компилятора вы используете, и вы хотите, чтобы мы выполнили вашу работу за вас. (Конечно, вы ** можете использовать ** C++ 03.). Также отредактируйте свой вопрос. Теги для тегов. Комментарии не предназначены для редактирования. – sehe

+0

«Возможно, мне нужно будет взять Предикат, чтобы разрешить фильтрацию» - я проигнорировал это, поскольку он не является частью вопроса, и неясно, что это значит (я могу придумать несколько разных вещей, которые это может означать). – sehe

ответ

0

Я не вижу никаких требований в тексте для создания пользовательских итераторов. Вы можете просто набрать итераторы с внутренних карт.

Здесь я исправил некоторые вещи:

  • вы не можете, как правило, применяются boost::hash<Node> к Node const*. Если вы не укажете хэш, он будет по умолчанию boost::hash<key_type>, что очень вероятно, что вы хотите.

  • Были некоторые проблемы с корректностью константы (методы equal_range принимают указатели const). Я скорректировал все по отношению к безопасному дефолту constness.

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; 
} 
+0

Тип значения unordered_map - это вектор. И мой не является multimap или unordered_multimap, что я могу использовать equal_range напрямую. Причина, по которой я использую вектор, заключается в том, что я хотел бы сортировать элементы определенным образом после полной заполненности модели. Но я думаю, что получаю вашу мысль - я могу также набрать итератор на вектор и предоставить api, используя это. – soumeng78

+0

На самом деле это не моя точка зрения. Вы просто ничего не говорили о ожидаемом поведении, и я не считал сложность там, где он не был дан. – sehe

Смежные вопросы