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_IMPLnamespace 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]; }  };}#endifFile main.cpp#include <stdio.h>#include graph.hppint 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;} 
STL-like graph implementation
c++;classes;graph;stl
your node type doesn't seem to be a node, but an edge (or an adjacency relationship, or something). Unless this implementation is based on some literature which describes entries in the adjacency list as nodes, I'd consider renaming itI have no idea what mask and masking are supposed to mean. They may be meaningful names in the context where you're using this graph, but it isn't clear that they are in a generic graph. It's just where the user attaches their arbitrary data to each vertex, right? Is it even used?the number of vertices is fixed at creation time, and you can only add edges. Is that sensible?graph::insert doesn't check whether from and to are valid indiceswhat does digraph mean here - directed graph? Because there is another meaning which is totally unrelated. Why not just say directed?it looks like graph::V is always identical to adj.size() (and is anyway never used), so you can remove itvertex_impl is an internal implementation detail, yet you're exposing it. STL containers hide these details (list & tree nodes for example) inside the iterator, and only expose the user data. Is there a useful way of iterating transparently over the graph without exposing this?