为 GraphViz 的 Boost Graph 包输出重载流运算符
Overloading streaming operators for a Boost Graph bundle output for GraphViz
是否可以使用标准库类型的 Boost Graph 库中的捆绑属性,同时还使用该类型的 <<
流运算符重载来满足 write_graphviz
?
#include <boost/graph/graphviz.hpp>
namespace boost {
namespace detail {
namespace has_left_shift_impl {
template <typename T>
inline std::ostream &operator<<(std::ostream &o, const std::array<T,2> &a) {
o << a[0] << ',' << a[1];
return o;
}
}
}
}
static_assert(boost::has_left_shift<
std::basic_ostream<char>,
std::array<double,2>
>::value,"");
int main()
{
using namespace boost;
typedef adjacency_list<vecS, vecS, directedS, no_property, std::array<double,2>> Graph;
Graph g;
add_edge(0, 1, {123,456}, g);
write_graphviz(std::cout, g, default_writer(),
make_label_writer(boost::get(edge_bundle,g)));
return 0;
}
面对Boost static assert,我将代码修改为上面的代码;采纳 here 的建议,其中 <<
实现是在 boost::detail::has_left_shift_impl
命名空间中定义的。 las,我现在面临另一个错误:
/usr/include/boost/lexical_cast.hpp:1624:50: error: cannot bind ‘std::basic_ostream<char>’ lvalue to ‘std::basic_ostream<char>&&’
bool const result = !(out_stream << input).fail();
有没有办法提供 <<
的重载以供 write_graphviz
使用?我正在使用 Ubuntu 14.10 和 GCC 4.9.1。
你甚至做不到
std::cout << g[add_edge(0,1,{123,456},g)];
没有提供例如
inline static std::ostream& operator<<(std::ostream& os, std::array<double, 2> const& doubles) {
return os << "{" << doubles[0] << "," << doubles[1] << "}";
}
现在让 lexical_cast
在正确的时间看到这些重载非常难以移植(主要是因为 ADL 无法帮助您处理 std::array
和 double
)。
相反 您可以使用值转换 属性 映射(当然是只读的):
std::string prettyprint(std::array<double, 2> const& arr) {
std::ostringstream oss;
oss << "{" << arr[0] << "," << arr[1] << "}";
return oss.str();
}
然后是make_transform_value_property_map(prettyprint, get(edge_bundle, g))
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graphviz.hpp>
using namespace boost;
std::string prettyprint(std::array<double, 2> const& arr) {
std::ostringstream oss;
oss << "{" << arr[0] << "," << arr[1] << "}";
return oss.str();
}
int main()
{
using namespace boost;
typedef adjacency_list<vecS, vecS, directedS, no_property, std::array<double,2>> Graph;
Graph g;
add_edge(0, 1, {123,456}, g);
write_graphviz(std::cout, g, default_writer(),
make_label_writer(make_transform_value_property_map(&prettyprint, get(edge_bundle, g))));
}
版画
digraph G {
0;
1;
0->1 [label="{123,456}"];
}
是否可以使用标准库类型的 Boost Graph 库中的捆绑属性,同时还使用该类型的 <<
流运算符重载来满足 write_graphviz
?
#include <boost/graph/graphviz.hpp>
namespace boost {
namespace detail {
namespace has_left_shift_impl {
template <typename T>
inline std::ostream &operator<<(std::ostream &o, const std::array<T,2> &a) {
o << a[0] << ',' << a[1];
return o;
}
}
}
}
static_assert(boost::has_left_shift<
std::basic_ostream<char>,
std::array<double,2>
>::value,"");
int main()
{
using namespace boost;
typedef adjacency_list<vecS, vecS, directedS, no_property, std::array<double,2>> Graph;
Graph g;
add_edge(0, 1, {123,456}, g);
write_graphviz(std::cout, g, default_writer(),
make_label_writer(boost::get(edge_bundle,g)));
return 0;
}
面对Boost static assert,我将代码修改为上面的代码;采纳 here 的建议,其中 <<
实现是在 boost::detail::has_left_shift_impl
命名空间中定义的。 las,我现在面临另一个错误:
/usr/include/boost/lexical_cast.hpp:1624:50: error: cannot bind ‘std::basic_ostream<char>’ lvalue to ‘std::basic_ostream<char>&&’
bool const result = !(out_stream << input).fail();
有没有办法提供 <<
的重载以供 write_graphviz
使用?我正在使用 Ubuntu 14.10 和 GCC 4.9.1。
你甚至做不到
std::cout << g[add_edge(0,1,{123,456},g)];
没有提供例如
inline static std::ostream& operator<<(std::ostream& os, std::array<double, 2> const& doubles) {
return os << "{" << doubles[0] << "," << doubles[1] << "}";
}
现在让 lexical_cast
在正确的时间看到这些重载非常难以移植(主要是因为 ADL 无法帮助您处理 std::array
和 double
)。
相反 您可以使用值转换 属性 映射(当然是只读的):
std::string prettyprint(std::array<double, 2> const& arr) {
std::ostringstream oss;
oss << "{" << arr[0] << "," << arr[1] << "}";
return oss.str();
}
然后是make_transform_value_property_map(prettyprint, get(edge_bundle, g))
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graphviz.hpp>
using namespace boost;
std::string prettyprint(std::array<double, 2> const& arr) {
std::ostringstream oss;
oss << "{" << arr[0] << "," << arr[1] << "}";
return oss.str();
}
int main()
{
using namespace boost;
typedef adjacency_list<vecS, vecS, directedS, no_property, std::array<double,2>> Graph;
Graph g;
add_edge(0, 1, {123,456}, g);
write_graphviz(std::cout, g, default_writer(),
make_label_writer(make_transform_value_property_map(&prettyprint, get(edge_bundle, g))));
}
版画
digraph G {
0;
1;
0->1 [label="{123,456}"];
}