Compiler error using iterator: " error: ‘... ::iterator’ has no member named '...' "
find(it_edge.start)
This tries to access a data member start
of the object it_edge
. it_edge
is an iterator:
typename std::vector<graph<Object, Weight>::Edge*>::iterator it_edge;
You probably want to access the data member start
of the Edge
object this iterator (indirectly) points to.
If you apply an indirection via *
to an iterator, you'll get the (a reference to) the object the iterator points to:
*it_edge // returns an Edge*
You'll need a second indirection to get the Edge
object this pointer points to:
**it_edge // returns an Edge object (lvalue)
Then, you can access the data member start
of this object:
(**it_edge).start
Typically, ->
is applied recursively until the operand is a pointer. So I thought at first that
it_edge->start
would work as well.
However, Standard Library iterators are required to implement a->m
as (*a).m
[input.iterators]/Table 107. Therefore, the iterator class returns a pointer to the element pointed to from its overloaded operator->
:
template<class T>
class iterator
{
private:
T* ptr;
public:
T* operator->() { return ptr; }
};
In the OP, we have T == Edge*
, so T* == Edge**
, and that's why
it_edge->start
doesn't work. However,
(*it_edge)->start
works fine, since it also applies the two necessary indirections.
user3210680
Updated on June 04, 2022Comments
-
user3210680 almost 2 years
Below is the code. More relevant bits lie under Class Edge and Vertex, with the error throwing copy-constructor below the initial block. I know for sure this has to do with how I'm calling end and start, seeing as how they're of type Vertex* in the Edge() class, and that I'm calling them with an iterator of type std::vector::Edge*>. It's something pointer based. Yes, this is for class, but it's a class project with more to it and this is just one error I've gotten stuck on. Thanks ahead of time, I'm probably just not seeing something obvious because of sleep deprivation or something.
#ifndef GRAPH_H #define GRAPH_H #include <vector> #include <limits> #include <string> #include <iostream> #include <fstream> using namespace std; template <typename Object, typename Weight> class graph { public: class Vertex; class Edge { public: Edge(Vertex* v, Vertex* w, Weight setweight) { start = v; end = w; v->edge.push_back(this); w->inedge.push_back(this); weight = setweight; explored = false; } Edge() { explored = false; } Weight weight; Vertex* start; Vertex* end; bool explored; }; class Vertex { public: Vertex(Object setelement) { level = 0; connectedcomponent = 0; element = setelement; back = NULL; explored = false; } Vertex() { level = 0; connectedcomponent = 0; back = NULL; explored = false; } Object element; vector<Edge*> edge; vector<Edge*> inedge; double value; size_t starttime, finishtime; size_t level; size_t connectedcomponent; float rank; Vertex* back; int color; bool explored; }; private: vector<Edge*> edge; vector<Vertex*> vertex; size_t counter; public: graph(); graph(graph& G); ~graph(); void reset(); void resetBack(); void resetValues(); void resetLevels(); void resetExplored(); void resetConnectedComponents(); vector<Vertex*> incidentVertices(Vertex* v); vector<Edge*> incidentEdges(Vertex* v); vector<Edge*> outgoingEdges(Vertex* v); vector<Vertex*> adjacentVertices(Vertex* v); size_t indegree(Vertex* v); size_t outdegree(Vertex* v); size_t degree(Vertex* v); Vertex* startVertex(Edge* e); Vertex* endVertex(Edge* e); bool isAdjacent(Vertex* v, Vertex* w); Vertex* insertVertex(Object o); void insertEdge(Vertex* v, Vertex* w, Weight t); void insertUndirectedEdge(Vertex* v, Vertex* w, Weight t); void removeVertex(Vertex* v); void removeEdge(Edge* e); size_t numVertices(); size_t numEdges(); vector<Vertex*> vertices(); vector<Edge*> edges(); void print(); void read_file(std::string filename); }; template <typename Object, typename Weight> graph<Object, Weight>::graph() {//Default Constructor Edge(); Vertex(); counter = 0; }
Copy Constructor, which generates the error (I know this is iterator based)
Graph.h:149:22: error: ‘std::vector::Edge*, std::allocator::Edge*> >::iterator’ has no member named ‘start’ find(it_edge.start),find(it_edge.end),(*(it_edge))->weight)); ^
Graph.h:149:40: error: ‘std::vector::Edge*, std::allocator::Edge*> >::iterator’ has no member named ‘end’ find(it_edge.start),find(it_edge.end),(*(it_edge))->weight)); ^
template <typename Object, typename Weight> graph<Object, Weight>::graph(graph<Object, Weight>& G) {//Copy Constructor typename std::vector<graph<Object, Weight>::Vertex*>::iterator it_vert; for(it_vert = vertex.begin(); it_vert != vertex.end(); ++it_vert){ vertex.push_back(new Vertex((*(it_vert))->element)); } typename std::vector<graph<Object, Weight>::Edge*>::iterator it_edge; for(it_edge = edge.begin(); it_edge != edge.end(); ++it_edge){ edge.push_back(new Edge( find(it_edge.start),find(it_edge.end),(*(it_edge))->weight)); } }
-
user3210680 about 10 yearsSorry, I was out of wifi range. I tried that once before too, it gives me this verbose error Graph.h:149:26: error: no matching function for call to ‘find(graph<char, int>::Vertex*&)’ find((*it_edge)->start),find((*it_edge)->end),(*(it_edge))->weight)); ^ Graph.h:149:26: note: candidates are: In file included from /usr/include/c++/4.8/bits/locale_facets.h:48:0, from /usr/include/c++/4.8/bits/basic_ios.h:37, ...etc..... pasting all of it runs about 3.2k characers above the limit. The errors mostly read the same as this one
-
dyp about 10 yearsYes, I got this error too when trying to compile your program. I thought you showed only a part of it here. Which function
find
do you want to call? -
user3210680 about 10 yearsI was calling std::find(). That seemed to be the problem. If I did call pointers correctly, it was trying to find a Vertex* in an Edge* vector. I ended up changing the code implementation which fixed the issue, though, I'm unfortunately not getting the deep copy I wanted. Regardless, the issue at hand is resolved, so thank you very much.
-
dyp about 10 yearsCalling
std::find
requires two arguments (so, e.g.find((**it_edge).start, (**it_edge).end)
) and it requires including the<algorithm>
header. As for the deep copy: That would be much easier if you wouldn't use owning raw pointers in thegraph
class (e.g.vector<Edge*> edge; vector<Vertex*> vertex;
). -
user3210680 about 10 yearsoh yeah, I did try that, but it was not happy finding the vertices through the edge vector. I'm going to rethink my deep copy as a whole from here
-
dyp about 10 yearsI'm sorry - it's not my day.
find
needs three arguments (start and begin of the range, plus a value to find). It searches by using equality (==
), but as you supply pointers, the equality would be between a pointer and the weight. I don't quite understand what you want to find there, though. -
user3210680 about 10 yearsI thought so haha. That's fine, you're trying to help.
for(it_edge = G.edge.begin(); it_edge != G.edge.end(); ++it_edge){ edge.push_back(new Edge((*it_edge)->start,(*it_edge)->end, (*it_edge)->weight)); }
Anyways, the following code ended up working. I didn't actually need 'find' like I previously was led to believe. This allowed me to get rid of a nasty seg fault after investigating one of my deletion functions, which allowed me to actually debug the rest of the program.. etc. The code lived happily ever after.