Search code examples
c++boostgraphboost-graph

How can I solve this error in Printing Nodes and Edges Boost Graph Library?


I have written the following function to print out just the size of My Graph Nodes and Edges, but this function didn't work, the Error was : error: invalid use of non-static data member 'MyGraph'

typedef adjacency_list < vecS, vecS, directedS, property < vertex_name_t, idType >, property < edge_weight_t, double > > graph_t;
class MyGraphBuilder{
private:
graph_t MyGraph;
}
void MyGraphBuilder::printGraph(MyGraphBuilder::MyGraph){
unsigned long long NodesCount = num_vertices(MyGraphBuilder::MyGraph);
cout<<"Number of Vertices is :\t"<<NodesCount<<"\n";
unsigned long long EdgesCount = num_edges(MyGraphBuilder::MyGraph);
cout<<"Number of Vertices is :\t"<<EdgesCount<<"\n";
}

Solution

  • MyGraphBuilder::MyGraph names a type. If you want to pass a parameter and use it, you'll have to name it:

    void MyGraphBuilder::printGraph(MyGraphBuilder::MyGraph g) {
        cout << "Number of Vertices is :\t" << num_vertices(g) << "\n";
        cout << "Number of Edges is :\t" << num_edges(g) << "\n";
    }
    

    To be more efficient you can pass by reference (in this case, const& will work because you're not modifying the graph) to avoid copying the entire graph just for the call to printGraph:

    void MyGraphBuilder::printGraph(MyGraphBuilder::MyGraph const& g) const {
        cout << "Number of Vertices is :\t" << num_vertices(g) << "\n";
        cout << "Number of Edges is :\t" << num_edges(g) << "\n";
    }
    

    Note how I marked the member function const as well, because we can.

    Alternatively you can mark is as a static member function because you're passing the graph in, anyways, we are not using members of MyGraphBuilder at all. Honestly, that feels like printGraph should not be a member of that class in the first place.


    Bonus:

    Be advised that there is a print_graph utility in boost/graph/graph_utility.hpp already. How to make it print the properties you want depends on the actual type of your graph, so here's a pretty random example:

    Live On Coliru

    #include <boost/graph/adjacency_list.hpp>
    #include <boost/graph/graph_utility.hpp>
    #include <iostream>
    #include <random>
    
    using boost::make_iterator_range;
    
    struct VertexProperties { std::string name; };
    struct EdgeProperties { double weight = 0; };
    
    struct MyGraphBuilder {
        using MyGraph = boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, VertexProperties, EdgeProperties>;
    
        MyGraphBuilder(MyGraph& g) : _target(g) {}
        void generate();
    
      private:
        MyGraph& _target;
    };
    
    void printGraph(MyGraphBuilder::MyGraph const& g) {
        std::cout << "Number of Vertices is:" << num_vertices(g) << "\n";
        std::cout << "Number of Edges is:" << num_edges(g) << "\n";
    
        boost::print_graph(g, boost::get(&VertexProperties::name, g), std::cout);
    
        // to print with edge weights:
        for (auto v : make_iterator_range(vertices(g))) {
            for (auto oe : make_iterator_range(out_edges(v, g))) {
                std::cout << "Edge " << oe << " weight " << g[oe].weight << "\n";
            }
        }
    }
    
    #include <boost/graph/random.hpp>
    void MyGraphBuilder::generate() {
        std::mt19937 prng { 42 }; // fixed random seed
        boost::generate_random_graph(_target, 5, 5, prng);
    
        _target[0].name = "one";
        _target[1].name = "two";
        _target[2].name = "three";
        _target[3].name = "four";
        _target[4].name = "five";
    
        for (auto e : boost::make_iterator_range(edges(_target))) {
            _target[e].weight = std::uniform_real_distribution<>(1.0, 10.0)(prng);
        }
    }
    
    int main() {
        MyGraphBuilder::MyGraph g;
    
        {
            MyGraphBuilder builder{g};
            builder.generate();
        }
    
        printGraph(g);
    }
    

    Printing:

    Number of Vertices is:5
    Number of Edges is:5
    one --> 
    two --> four 
    three --> one one 
    four --> three 
    five --> one 
    Edge (1,3) weight 1.52275
    Edge (2,0) weight 8.79559
    Edge (2,0) weight 6.41004
    Edge (3,2) weight 7.37265
    Edge (4,0) weight 1.18526