0

I have 2 files, one is a .h file which contains my declarations and another is a .tem file which contains the implementation of my .h file. I'm having issues with the iterator for begin() and end() for my graph node iterator (shown below in "// Iterators for Graph nodes"), which is supposed to return the iterator pointing at the begin or end of an iterated graph.

The following is my code in the Graph.h:

#ifndef _Graph_h
#define _Graph_h

#include <vector>
#include <algorithm>
#include <string>
#include <memory>
#include <iostream>
#include <exception>
#include <map>
#include <set>
#include <typeinfo>


namespace gdwg {

    template <typename N, typename E> class Graph; // function prototype for Graph class

//-----------------------------------------------------------
// Iterators for Graph with Nodes N and Edges E
//-----------------------------------------------------------

    // Iterator class for Node N
    template <typename N, typename E> class Node_Iterator {

    ******* Some code for public and private members of Node_Iterator

    };

    // Iterator class for Edge E
    template <typename N, typename E> class Edge_Iterator {

    ******* Some code for public and private members of Edge_Iterator

    };

template <typename N, typename E> class Graph {

    private:
        struct Node;
        struct Edge;

        struct Node {
            N val_;
            int numEdges_;
            std::set<std::shared_ptr<Edge>> edges_;
            Node() {}
            Node(const N x) : val_{x} { numEdges_=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();
        };

    public:

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


        ******* Some code for public members of Graph

        // Iterators for Graph nodes
        Node_Iterator<N, E> begin() const;

        Node_Iterator<N, E> end() const;


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


};

    #include "Graph.tem" // definition and implementation of Node_Iterator, Edge_Iterator and Graph classes

}

#endif

This is the definition in the .tem file for the iterators:

template <typename N, typename E>
Graph<N, E>::Node_Iterator<N, E> Graph<N, E>::begin() const { 
    return Node_Iterator<N, E>(&Graph<N, E>::nodes_);
}

template <typename N, typename E>
Graph<N, E>::Node_Iterator<N, E> Graph<N, E>::end() const { 
    return Node_Iterator<N, E>(nullptr);
}

When I tried to compile it, there was the following error code (I will just put the error code for begin() coz the end() error is similar):

tests/Graph.tem:336:14: error: non-template ‘Node_Iterator’ used as template
 Graph<N, E>::Node_Iterator<N, E> Graph<N, E>::begin() const {
              ^~~~~~~~~~~~~
tests/Graph.tem:336:14: note: use ‘gdwg::Graph<N, E>::template Node_Iterator’ to indicate that it is a template
tests/Graph.tem:336:1: error: need ‘typename’ before ‘gdwg::Graph<N, E>::Node_Iterator’ because ‘gdwg::Graph<N, E>’ is a dependent scope
 Graph<N, E>::Node_Iterator<N, E> Graph<N, E>::begin() const {
 ^~~~~~~~~~~

So I did what it said and added "typename" in front of Graph and also made it a template. But it came up with this error instead:

tests/Graph.tem:336:52: error: prototype for ‘typename gdwg::Graph<N, E>::Node_Iterator<N, E> gdwg::Graph<N, E>::begin() const’ does not match any in class ‘gdwg::Graph<N, E>’
 typename Graph<N, E>::template Node_Iterator<N, E> Graph<N, E>::begin() const {
                                                    ^~~~~~~~~~~
In file included from tests/test1.cpp:3:0:
tests/Graph.h:322:23: error: candidate is: gdwg::Node_Iterator<N, E> gdwg::Graph<N, E>::begin() const
   Node_Iterator<N, E> begin() const;
                       ^~~~~

So I removed the Graph in front of begin() as I thought it was the problem, but got another error instead:

tests/Graph.tem:336:60: error: non-member function ‘typename gdwg::Graph<N, E>::Node_Iterator<N, E> gdwg::begin()’ cannot have cv-qualifier
 typename Graph<N, E>::template Node_Iterator<N, E> begin() const {
                                                            ^~~~~

Can someone tell me what I'm doing wrong?

iteong
  • 715
  • 3
  • 10
  • 26
  • where is your class "graph" defined? I can see the definitions of the member function of the class but where are it's declarations? – Hayt Sep 12 '16 at 11:53
  • Its declarations are in the .h file, while its definitions are in the .tem file. The .tem file definitions only define those functions that has implementation code. – iteong Sep 12 '16 at 11:55
  • Ah sorry. Overlooked that somehow. – Hayt Sep 12 '16 at 12:00
  • Got any idea what is wrong? =( – iteong Sep 12 '16 at 12:01

1 Answers1

1

Node_Iterator is not a sub-class of Graph so Graph<N, E>::Node_Iterator<N, E> cannot be found. Simply change the definition to this should work:

template <typename N, typename E>  
Node_Iterator<N,E> Graph<N,E>::begin() const { 
    return Node_Iterator<N,E>(&Graph<N, E>::nodes_);
}
Hayt
  • 5,210
  • 30
  • 37
  • I got the following errors: tests/Graph.tem:342:12: error: no matching function for call to ‘gdwg::Node_Iterator::Node_Iterator(std::map::Node>, std::less, std::allocator::Node> > > > gdwg::Graph::*)’ return Node_Iterator(&Graph::nodes_); – iteong Sep 12 '16 at 12:22
  • tests/Graph.tem:80:1: note: candidate: gdwg::Node_Iterator::Node_Iterator(const std::map::Node> >*) [with N = int; E = int; typename gdwg::Graph::Node = gdwg::Graph::Node] Node_Iterator::Node_Iterator(const std::map> *nodes) { ^~~~~~~~~~~~~~~~~~~ – iteong Sep 12 '16 at 12:23
  • In file included from tests/test1.cpp:3:0: tests/Graph.h:33:42: note: candidate: gdwg::Node_Iterator::Node_Iterator(const gdwg::Node_Iterator&) template class Node_Iterator { ^~~~~~~~~~~~~ – iteong Sep 12 '16 at 12:24
  • tests/Graph.h:33:42: note: no known conversion for argument 1 from ‘std::map::Node>, std::less, std::allocator::Node> > > > gdwg::Graph::*’ to ‘const gdwg::Node_Iterator&’ – iteong Sep 12 '16 at 12:24
  • tests/Graph.tem: In instantiation of ‘gdwg::Node_Iterator gdwg::Graph::begin() const [with N = std::__cxx11::basic_string; E = double]’: tests/Graph.tem:328:22: required from ‘void gdwg::Graph::printNodes() const [with N = std::__cxx11::basic_string; E = double]’ – iteong Sep 12 '16 at 12:27
  • well that is another error which just follows after you fixed the one you were asking for. this depends on your constructor for `node_iterator` – Hayt Sep 12 '16 at 12:27
  • and putting your error messages in the comments won't help in any case. – Hayt Sep 12 '16 at 12:27
  • Is the one I asked for fixed? So this is something else related to the return value? – iteong Sep 12 '16 at 12:28
  • `Node_Iterator Graph::begin() const { `this part is fixed: now the next line `return Node_Iterator(&Graph::nodes_);` won't compile because it seems like Node_Iterator is lacking the appropriate constructors. (cannot tell for sure though because error messages in command are even more unreadable) But it seems to me like this particular problem is done. Stackoverflow can't walk you through every template error though. – Hayt Sep 12 '16 at 12:32
  • Yes I had to change &Graph::nodes_ to &nodes_ and it compiles now. Thanks!! =) – iteong Sep 12 '16 at 12:36