I have implemented an STL-like graph class. Could someone review it and tell me things that I could add to it?
File graph.hpp
#include <vector>
#include <list>
using std::vector;
using std::list;
#ifndef GRAPH_IMPL
#define GRAPH_IMPL
namespace graph {
struct node
{
int v,w;
};
template<class T, bool digraph>
class graph;
template<class T>
class vertex_impl
{
friend class graph<T,true>;
friend class graph<T,false>;
private:
list<node> adj;
int index;
T masking;
public:
vertex_impl(int index = -1, const T& masking = T()) : index(index), masking(masking){}
vertex_impl(const vertex_impl& other) : index(other.index), masking(other.masking){}
typedef typename list<node>::iterator iterator;
typedef typename list<node>::const_iterator const_iterator;
typedef typename list<node>::reverse_iterator reverse_iterator;
typedef typename list<node>::const_reverse_iterator const_reverse_iterator;
typedef typename list<node>::size_type size_type;
iterator begin() { return adj.begin(); }
const_iterator begin() const { return adj.begin(); }
iterator end() { return adj.end(); }
const_iterator end() const { return adj.end(); }
reverse_iterator rbegin() { return adj.rbegin(); }
const_reverse_iterator rbegin() const { return adj.begin(); }
reverse_iterator rend() { return adj.rend(); }
const_reverse_iterator rend() const { return adj.rend(); }
size_type degree() const { return adj.size(); }
int name() const { return index; }
const T& mask() const { return masking; }
void set_mask(const T& msk) { masking = msk; }
};
template<class T, bool digraph>
class graph
{
private:
vector<vertex_impl<T> > adj;
typename vector<vertex_impl<T> >::size_type V,E;
public:
typedef vertex_impl<T> vertex;
typedef typename vector<vertex>::iterator iterator;
typedef typename vector<vertex>::const_iterator const_iterator;
typedef typename vector<vertex>::reverse_iterator reverse_iterator;
typedef typename vector<vertex>::const_reverse_iterator const_reverse_iterator;
typedef typename vector<vertex>::size_type size_type;
graph(size_type v) : adj(v), V(v), E(0)
{
for(size_type i = 0; i < v; ++i) {
adj[i].index = i;
}
}
iterator begin() { return adj.begin(); }
const_iterator begin() const { return adj.begin(); }
iterator end() { return adj.end(); }
const_iterator end() const { return adj.end(); }
reverse_iterator rbegin() { return adj.rbegin(); }
const_reverse_iterator rbegin() const { return adj.rbegin(); }
reverse_iterator rend() { return adj.rend(); }
const_reverse_iterator rend() const { return adj.rend(); }
void insert(int from, int to, int weight = 1)
{
adj[from].adj.push_back((node){to,weight});
E++;
if(!digraph)
adj[to].adj.push_back((node){from,weight});
}
void erase(int from, int to)
{
for(typename vertex::iterator i = adj[from].begin(); i != adj[from].end();) {
if(i->v == to) {
i = adj[from].adj.erase(i);
E--;
} else {
++i;
}
}
if(!digraph) {
for(typename vertex::iterator i = adj[to].begin(); i != adj[to].end();) {
if(i->v == from) {
i = adj[to].adj.erase(i);
} else {
++i;
}
}
}
}
size_type vertices() const { return V; }
size_type edges() const { return E; }
vertex& operator[](int i) { return adj[i]; }
const vertex& operator[](int i) const { return adj[i]; }
};
}
#endif
File main.cpp
#include <stdio.h>
#include "graph.hpp"
int main()
{
graph::graph<char*,false> gr(5);
int m;
scanf("%d", &m);
for(int i=0; i<m; ++i) {
int a,b;
scanf("%d %d", &a, &b);
gr.insert(a,b);
}
for(graph::graph<char*,false>::size_type i = 0; i < 5; ++i) {
printf("%d: ", gr[i].name());
for(graph::graph<char*,false>::vertex::iterator j = gr[i].begin(); j != gr[i].end(); ++j) {
printf(" %d", j->v);
}
printf("\n");
}
return 0;
}