Search code examples
c++boostboost-graph

failed to use property_map and compressed_sparse_row_graph in boost library


I have read the boost docs to figure out how to use property_map.

Based on

// Property map accessors
template<typename PropertyTag>
property_map<compressed_sparse_row_graph, PropertyTag>::type
get(PropertyTag, compressed_sparse_row_graph& g)

I wrote the following code:

#include <boost/graph/graph_traits.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/compressed_sparse_row_graph.hpp>
#include <boost/utility.hpp>

typedef boost::compressed_sparse_row_graph<boost::bidirectionalS, boost::no_property, boost::property<boost::edge_weight_t, int> > AdjGraph;
typedef typename boost::property_map<AdjGraph, boost::edge_weight_t>::type WeightMap;
class data {
    WeightMap weight;
    data()
    {
        std::vector<std::pair<int, int> > edges;
        std::vector<int> edgesAttr;
        boost::shared_ptr<AdjGraph> adjGraph;
        adjGraph = boost::shared_ptr<AdjGraph>(new AdjGraph(boost::edges_are_unsorted_multi_pass, edges.begin(), edges.end(), edgesAttr.begin(), 0));
        weight = boost::get(boost::edge_weight, *adjGraph);
    }
};

int main() { return 0; }

But errors were reported when I tried to compiled it.

I modified

weight = boost::get(boost::edge_weight, *adjGraph);

to be

auto tmp = boost::get(boost::edge_weight, *adjGraph);

And it compiles well.

But as "weight" should not be a static variable, "auto weight" is unacceptable.

I want to know what type "weight" should be. I tried "typeinfo" and "typeid().name()" but the output is unreadable.

Though I refer to 1.61 docs, I am actually using 1.58 1.58 docs


Solution

  • I want to know what type "weight" should be

    The type is WeightMap. You already have it correct. You're solving the wrong problem. This simply compiles

    WeightMap weight = boost::get(boost::edge_weight, *adjGraph);
    

    Then what is the problem?

    WeightMap is not default-constructible. Like all property-maps it's just a lightweight, low-cost-copyable "reference" to the actual data (in this case inside the graph model).

    Therefore, there is zero reason to store it in a member, or share it to the outside world.

    On a more essential level, because property-maps are usually (and certainly in this case) references to an underlying object, its lifetime is only valid as long as the underlying graph is.

    Therefore it doesn't make sense to keep the weight map in a member unless you also keep a shared pointer to the graph in an earlier member:

    Live On Wandbox

    #include <boost/graph/graph_traits.hpp>
    #include <boost/graph/compressed_sparse_row_graph.hpp>
    #include <boost/utility.hpp>
    
    typedef boost::compressed_sparse_row_graph<boost::bidirectionalS, boost::no_property, boost::property<boost::edge_weight_t, int> > AdjGraph;
    typedef typename boost::property_map<AdjGraph, boost::edge_weight_t>::type WeightMap;
    
    class data {
        boost::shared_ptr<AdjGraph> adjGraph;
        WeightMap weight;
      public:
        data(std::vector<std::pair<int, int> > const& edges, std::vector<int> const& edgesAttr) 
            : adjGraph (boost::shared_ptr<AdjGraph>(new AdjGraph(boost::edges_are_unsorted_multi_pass, edges.begin(), edges.end(), edgesAttr.begin(), 0))),
              weight(boost::get(boost::edge_weight, *adjGraph))
        {
        }
    };
    
    int main() {
        std::vector<std::pair<int, int> > edges;
        std::vector<int> edgesAttr;
    
        data d(edges, edgesAttr);
    }