Firstly, you have to pass the property map to dynamic_properties:
dpDual.property("Color_1", vOne); // or maaaaybe
dpDual.property("Color_1", boost::get(vertex_one, g));
Secondly, Graphviz is inherently a text format. Have you defined text-conversions for Color*
? If not, how would you like the properties to be presented?
Simple Solution
Why are the properties pointers? Color*
is more wasteful than Color
(int is potentially smaller than a pointer).
You can leave all the lifetime issues behind and have your wish:
inline static std::ostream& operator<<(std::ostream& os, Color color) {
return os << static_cast<int>(color);
}
inline static std::istream& operator>>(std::istream& is, Color& color) {
int dummy;
is >> dummy;
color = static_cast<Color>(dummy);
return is;
}
See Live On Coliru
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graphviz.hpp>
#include <boost/graph/random.hpp>
#include <random>
#include <iostream>
typedef enum { UNSET = 0, RED = 1, GREEN = 2, BLUE = 3} Color;
enum vertex_one_t { vertex_one };
namespace boost { BOOST_INSTALL_PROPERTY(vertex, one); }
enum vertex_two_t { vertex_two };
namespace boost {
BOOST_INSTALL_PROPERTY(vertex, two);
}
enum vertex_three_t { vertex_three };
namespace boost {
BOOST_INSTALL_PROPERTY(vertex, three);
}
typedef boost::property< boost::vertex_index_t, int,
boost::property< vertex_one_t, Color,
boost::property< vertex_two_t, Color,
boost::property< vertex_three_t, Color > > > > DualVertexProperty;
inline static std::ostream& operator<<(std::ostream& os, Color color) {
return os << static_cast<int>(color);
}
inline static std::istream& operator>>(std::istream& is, Color& color) {
int dummy;
is >> dummy;
color = static_cast<Color>(dummy);
return is;
}
int main() {
using DualGraph = boost::adjacency_list< boost::vecS, boost::vecS, boost::directedS, DualVertexProperty, boost::no_property>;
boost::dynamic_properties dpDual;
DualGraph g;
std::mt19937 rng { std::random_device{}() };
boost::generate_random_graph(g, 5, 5, rng);
boost::property_map<DualGraph, boost::vertex_index_t>::type vIndex = boost::get(boost::vertex_index, g);
boost::property_map<DualGraph, vertex_one_t>::type vOne = boost::get(vertex_one, g);
dpDual.property("node_id", vIndex);
dpDual.property("Color_1", vOne);
boost::write_graphviz_dp(std::cout, g, dpDual);
}
More complex
You can (try) to make the pointer streamable, but you'll have to think of a way to make the lifetimes and ownership make sense.
Bonus:
Consider bundled properties. Unless you have very specific requirements, there is no need to keep using the archaic internal properties like your code does.
Live On Coliru (compilation timed out)
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graphviz.hpp>
#include <boost/graph/random.hpp>
#include <random>
#include <iostream>
typedef enum { UNSET = 0, RED = 1, GREEN = 2, BLUE = 3} Color;
struct DualVertexProperty {
Color one, two, three;
};
inline static std::ostream& operator<<(std::ostream& os, Color color) { return os << static_cast<int>(color); }
inline static std::istream& operator>>(std::istream& is, Color& color) { int dummy; is >> dummy; color = static_cast<Color>(dummy); return is; }
int main() {
using DualGraph = boost::adjacency_list< boost::vecS, boost::vecS, boost::directedS, DualVertexProperty, boost::no_property>;
boost::dynamic_properties dpDual;
DualGraph g;
std::mt19937 rng { std::random_device{}() };
boost::generate_random_graph(g, 5, 5, rng);
for (auto v: boost::make_iterator_range(boost::vertices(g)))
g[v] = DualVertexProperty { RED, GREEN, BLUE };
dpDual.property("node_id", boost::get(boost::vertex_index, g));
dpDual.property("Color_1", boost::get(&DualVertexProperty::one, g));
boost::write_graphviz_dp(std::cout, g, dpDual);
}
That's a lot simpler in many ways!