I'm using an implementation of a boost graph with a boost::shared_ptr<Obj>
as an edge attribute. I have two class Obj
and Obj2
such that:
class Obj{
public:
Obj(){};
virtual func(){std::cout << "Obj func " << std::endl};
};
class Obj2: public Obj{
public:
Obj2(){};
virtual func(){std::cout << "Obj2 func " << std::endl};
};
I'm adding edges in the graph using a (simplified) function such as:
void addEdge(Vertex index, Vertex index2, const boost::shared_ptr<Obj>& edgeAttribute){
out = boost::add_edge(index, index2, edgeAttribute, graph).first;
}
That I call using :
Obj2* obj = new Obj2();
boost::shared_ptr<Obj2> obj_ptr(obj);
addEdge(index, index2, obj_ptr);
However later in my code when picking up the edge attribute by doing edgeAttr = graph[edge]
and then calling the function edgeAttr->func()
, I call Obj's func and not Obj2's.
As far as I understand, it means that somewhere my Objects are being sliced. Is this short example I gave supposed to slice my object when using boost:shared_ptr and BGL, or is it some other implementation problem of my own like the initialisation?
No the graph model does not slice any attribute (note, that "attribute" is actually called a bundled property).
In fact, it does never copy the Obj
or Obj2
because it just copies the shared_ptr<>
leading to shared ownership, as opposed to copying a property.
#include <boost/graph/adjacency_list.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <iostream>
class Obj {
public:
Obj(){};
virtual void func(std::ostream& os) { os << "Obj func\n"; };
};
class Obj2 : public Obj {
public:
Obj2(){};
virtual void func(std::ostream& os) { os << "Obj2 func\n"; };
};
// I'm adding edges in the graph using a (simplified) function such as:
using Graph = boost::adjacency_list<boost::vecS, boost::vecS,
boost::directedS, boost::no_property, boost::shared_ptr<Obj> >;
using Vertex = Graph::vertex_descriptor;
struct Program {
Program() : _graph(10) {}
void addEdge(Vertex index, Vertex index2, const boost::shared_ptr<Obj> &edgeAttribute) {
auto out = boost::add_edge(index, index2, edgeAttribute, _graph).first;
}
void sample_edges() {
Obj2 *obj = new Obj2();
boost::shared_ptr<Obj2> obj_ptr(obj);
addEdge(1, 2, boost::make_shared<Obj2>());
addEdge(2, 3, boost::make_shared<Obj >());
addEdge(3, 4, boost::make_shared<Obj2>());
addEdge(4, 5, boost::make_shared<Obj >());
addEdge(5, 6, boost::make_shared<Obj2>());
addEdge(6, 7, boost::make_shared<Obj >());
}
void debug_dump() const {
for (auto ed : boost::make_iterator_range(boost::edges(_graph))) {
_graph[ed]->func(std::cout << "Edge " << ed << ": ");
}
}
private:
Graph _graph;
};
int main() {
std::cout << "Demo edges:\n";
Program demo;
demo.sample_edges();
demo.debug_dump();
std::cout << "Copied edges:\n";
// copy the whole shebang
Program clone = demo;
clone.debug_dump();
}
Prints:
Demo edges:
Edge (1,2): Obj2 func
Edge (2,3): Obj func
Edge (3,4): Obj2 func
Edge (4,5): Obj func
Edge (5,6): Obj2 func
Edge (6,7): Obj func
Copied edges:
Edge (1,2): Obj2 func
Edge (2,3): Obj func
Edge (3,4): Obj2 func
Edge (4,5): Obj func
Edge (5,6): Obj2 func
Edge (6,7): Obj func