M
Mike
You have only declared those functions as friends, but you have not
(http://www.parashift.com/c++-faq-lite/templates.html#faq-35.16) says:
Another approach is to define the friend function within the class body
at the same moment you declare it to be a friend. For example:
#include <iostream>
template<typename T>
class Foo {
public:
Foo(T const& value = T());
friend Foo<T> operator+ (const Foo<T>& lhs, const Foo<T>& rhs)
{
...
}
friend std:stream& operator<< (std:stream& o, const Foo<T>& x)
{
...
}
private:
T value_;
};
But I tried defining add_edge before the graph class and just including
friend declaration for add_edge inside the graph class (see below). It
still didn't work.
This time I got: "template-id 'add_edge<>' for ... does not match any
template declaration" error message.
#include <iostream>
#include <list>
using namespace std;
template<typename EDGE, typename VERTEX> struct graph; // pre-declare
the template class itself
template<typename EDGE, typename VERTEX>
typename graph<EDGE,VERTEX>::edge_pointer
add_edge(
typename graph<EDGE,VERTEX>::vertex_pointer from,
typename graph<EDGE,VERTEX>::vertex_pointer to,
const EDGE& e=EDGE()
)
{
edges(from).push_back(make_pair(e,to));
typename graph<EDGE,VERTEX>::edge_pointer p = edges(from).end();
return --p;
}
template<typename VERTEX /*Vertex Satellite data*/, typename EDGE=string
/*Edge Satellite data*/> struct graph
{
struct EDGE_LIST
{
typedef list<pair<VERTEX, EDGE_LIST> > vertex_list;
typedef typename vertex_list::iterator vertex_pointer;
vertex_list V;
friend edge_list& edges(vertex_pointer p){return p->second.edges;}
vertex_pointer add_vertex(VERTEX v)
{
V.push_back(make_pair(v, EDGE_LIST()));
vertex_pointer p = V.end();
return --p;
}
friend edge_pointer add_edge<>(vertex_pointer from, vertex_pointer
to, const EDGE& e);
};
int main()
{
graph<int> G;
graph<int>::vertex_pointer a = G.add_vertex(1);
graph<int>::vertex_pointer b = G.add_vertex(2);
add_edge(a,b);
return 0;
}
This seem to contradict what C++ FAQdeclared the functions themselves in the outer scope. You need to add
those declarations to the global scope. In other words:
edge_list& edges(vertex_pointer p);
edge_pointer add_edge(vertex_pointer from, vertex_pointer to,
const EDGE& e=EDGE());
(http://www.parashift.com/c++-faq-lite/templates.html#faq-35.16) says:
Another approach is to define the friend function within the class body
at the same moment you declare it to be a friend. For example:
#include <iostream>
template<typename T>
class Foo {
public:
Foo(T const& value = T());
friend Foo<T> operator+ (const Foo<T>& lhs, const Foo<T>& rhs)
{
...
}
friend std:stream& operator<< (std:stream& o, const Foo<T>& x)
{
...
}
private:
T value_;
};
But I tried defining add_edge before the graph class and just including
friend declaration for add_edge inside the graph class (see below). It
still didn't work.
This time I got: "template-id 'add_edge<>' for ... does not match any
template declaration" error message.
#include <iostream>
#include <list>
using namespace std;
template<typename EDGE, typename VERTEX> struct graph; // pre-declare
the template class itself
template<typename EDGE, typename VERTEX>
typename graph<EDGE,VERTEX>::edge_pointer
add_edge(
typename graph<EDGE,VERTEX>::vertex_pointer from,
typename graph<EDGE,VERTEX>::vertex_pointer to,
const EDGE& e=EDGE()
)
{
edges(from).push_back(make_pair(e,to));
typename graph<EDGE,VERTEX>::edge_pointer p = edges(from).end();
return --p;
}
template<typename VERTEX /*Vertex Satellite data*/, typename EDGE=string
/*Edge Satellite data*/> struct graph
{
struct EDGE_LIST
{
};list said:>::iterator> > edges;
typedef typename edge_list::iterator edge_pointer;typedef list said:>::iterator> > edge_list;
typedef list<pair<VERTEX, EDGE_LIST> > vertex_list;
typedef typename vertex_list::iterator vertex_pointer;
vertex_list V;
friend edge_list& edges(vertex_pointer p){return p->second.edges;}
vertex_pointer add_vertex(VERTEX v)
{
V.push_back(make_pair(v, EDGE_LIST()));
vertex_pointer p = V.end();
return --p;
}
friend edge_pointer add_edge<>(vertex_pointer from, vertex_pointer
to, const EDGE& e);
};
int main()
{
graph<int> G;
graph<int>::vertex_pointer a = G.add_vertex(1);
graph<int>::vertex_pointer b = G.add_vertex(2);
add_edge(a,b);
return 0;
}