Compiler error using iterator: " error: ‘... ::iterator’ has no member named '...' "

12,220
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.

Share:
12,220
user3210680
Author by

user3210680

Updated on June 04, 2022

Comments

  • user3210680
    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
    user3210680 about 10 years
    Sorry, 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
    dyp about 10 years
    Yes, 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
    user3210680 about 10 years
    I 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
    dyp about 10 years
    Calling 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 the graph class (e.g. vector<Edge*> edge; vector<Vertex*> vertex;).
  • user3210680
    user3210680 about 10 years
    oh 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
    dyp about 10 years
    I'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
    user3210680 about 10 years
    I 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.