iteong - 1 year ago 47
C++ Question

# fake iterator operations for enumerating all the node values in a graph

I'm trying to have a fake iterator for enumerating all the node values in a graph. The graph can be abstracted in any sequence, as long as the sequence consists of all and only the nodes in the graph. There should be a mutable qualifier, and the 4 operations' implementations are short and supposed to be only 1 line per function.

The test case for the 4 fake iterator operations is as follow, it is supposed to print out a string of values of the graph nodes through the fake iterator operations:

``````gdwg::Graph<std::string,int>> g
for (g.begin(); !g.end(); g.next())
std::cout << g.value() << std::end;
``````

I declared the graph as the following:

``````template <typename N, typename E> class Graph {

private:
struct Node;
struct Edge;

struct Node {
N val_;
int numEdges_;
int numIncomingEdges_;
std::set<std::shared_ptr<Edge>> edges_;
std::set<std::shared_ptr<Edge>> incomingEdges_;
Node() {}
Node(const N x) : val_{x} { numEdges_=0; numIncomingEdges_=0; }
void printNode(N n);
~Node();
void update();
};

struct Edge {
std::weak_ptr<Node> orig;
std::weak_ptr<Node> dest;
E val_;
Edge(std::shared_ptr<Node> o, std::shared_ptr<Node> d, E x);
Edge() {};
void printEdge();
~Edge();
};

// fake iterator operations
void begin() const;
bool end() const;
void next() const;
const N& value() const;

public:

friend class Node_Iterator<N, E>;
friend class Edge_Iterator<N, E>;

private:
std::map< N, std::shared_ptr<Node> > nodes_;

// fake iterator to be used for the four operations begin(), end(), next() and value()
mutable typename std::map< N, std::shared_ptr<Node> >::iterator fakeIter_;

};
``````

The implementation of the 4 operations are as follows:

``````// void begin() const: Sets an internal iterator, i.e., ``pointer'' to the first element of a sequence.
template <typename N, typename E>
void Graph<N,E>::begin() const {
// gets iterator to the first key/value pair in map sequence
fakeIter_ = nodes_.begin();
}

// bool end() const: Returns true if the iterator goes past the last element of the sequence and false otherwise.
template <typename N, typename E>
bool Graph<N,E>::end() const {
// return true if iterator goes past last element, otherwise return false
return ((fakeIter_ == nodes_.end()) ? true : false);
}

// void next() const: Moves the iterator to the next element of the sequence.
template <typename N, typename E>
void Graph<N,E>::next() const {
fakeIter_ = std::next(fakeIter_, 1);
}

// const N& value() const: Returns the value of the node pointed to by the iterator.
template <typename N, typename E>
const N& Graph<N,E>::value() const {
return fakeIter_->second->val_;
}
``````

When I try to compile, there is a bunch of errors popping up. I'm just wondering whether I'm implementing the fake iterator operations correctly and if there is any way to improve it if need be?

``````tests/Graph.tem: In instantiation of ‘void gdwg::Graph<N, E>::begin() const [with N = unsigned int; E = int]’:
tests/test13.cpp:23:15:   required from here
tests/Graph.tem:713:12: error: no match for ‘operator=’ (operand types are ‘std::map<unsigned int, std::shared_ptr<gdwg::Graph<unsigned int, int>::Node>, std::less<unsigned int>, std::allocator<std::pair<const unsigned int, std::shared_ptr<gdwg::Graph<unsigned int, int>::Node> > > >::iterator {aka std::_Rb_tree_iterator<std::pair<const unsigned int, std::shared_ptr<gdwg::Graph<unsigned int, int>::Node> > >}’ and ‘std::map<unsigned int, std::shared_ptr<gdwg::Graph<unsigned int, int>::Node>, std::less<unsigned int>, std::allocator<std::pair<const unsigned int, std::shared_ptr<gdwg::Graph<unsigned int, int>::Node> > > >::const_iterator {aka std::_Rb_tree_const_iterator<std::pair<const unsigned int, std::shared_ptr<gdwg::Graph<unsigned int, int>::Node> > >}’)
fakeIter_ = nodes_.begin();

In file included from /usr/local/include/c++/6.1.0/map:60:0,
from tests/Graph.h:19,
from tests/test13.cpp:3:
/usr/local/include/c++/6.1.0/bits/stl_tree.h:174:12: note: candidate: constexpr std::_Rb_tree_iterator<std::pair<const unsigned int, std::shared_ptr<gdwg::Graph<unsigned int, int>::Node> > >& std::_Rb_tree_iterator<std::pair<const unsigned int, std::shared_ptr<gdwg::Graph<unsigned int, int>::Node> > >::operator=(const std::_Rb_tree_iterator<std::pair<const unsigned int, std::shared_ptr<gdwg::Graph<unsigned int, int>::Node> > >&)
struct _Rb_tree_iterator
^~~~~~~~~~~~~~~~~
/usr/local/include/c++/6.1.0/bits/stl_tree.h:174:12: note:   no known conversion for argument 1 from ‘std::map<unsigned int, std::shared_ptr<gdwg::Graph<unsigned int, int>::Node>, std::less<unsigned int>, std::allocator<std::pair<const unsigned int, std::shared_ptr<gdwg::Graph<unsigned int, int>::Node> > > >::const_iterator {aka std::_Rb_tree_const_iterator<std::pair<const unsigned int, std::shared_ptr<gdwg::Graph<unsigned int, int>::Node> > >}’ to ‘const std::_Rb_tree_iterator<std::pair<const unsigned int, std::shared_ptr<gdwg::Graph<unsigned int, int>::Node> > >&’
/usr/local/include/c++/6.1.0/bits/stl_tree.h:174:12: note: candidate: constexpr std::_Rb_tree_iterator<std::pair<const unsigned int, std::shared_ptr<gdwg::Graph<unsigned int, int>::Node> > >& std::_Rb_tree_iterator<std::pair<const unsigned int, std::shared_ptr<gdwg::Graph<unsigned int, int>::Node> > >::operator=(std::_Rb_tree_iterator<std::pair<const unsigned int, std::shared_ptr<gdwg::Graph<unsigned int, int>::Node> > >&&)
/usr/local/include/c++/6.1.0/bits/stl_tree.h:174:12: note:   no known conversion for argument 1 from ‘std::map<unsigned int, std::shared_ptr<gdwg::Graph<unsigned int, int>::Node>, std::less<unsigned int>, std::allocator<std::pair<const unsigned int, std::shared_ptr<gdwg::Graph<unsigned int, int>::Node> > > >::const_iterator {aka std::_Rb_tree_const_iterator<std::pair<const unsigned int, std::shared_ptr<gdwg::Graph<unsigned int, int>::Node> > >}’ to ‘std::_Rb_tree_iterator<std::pair<const unsigned int, std::shared_ptr<gdwg::Graph<unsigned int, int>::Node> > >&&’
``````

What that first error is saying is that, as your `begin` function is `const`, `nodes_.begin()` will return a `const_iterator`. This cannot be assigned to an `iterator`, the type of `fakeIter_`.
You'll need to remove the `const` from `begin`, change the type of `fakeIter_`, or change your implementation (`begin` should return an iterator, not void).