c++ - 为 GraphViz 的 Boost Graph 捆绑输出重载流运算符

标签 c++ boost graphviz boost-graph boost-property-map

是否可以使用 Boost Graph Library 中的捆绑属性和标准库类型,同时还使用该类型的 << 流运算符重载来满足 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 静态断言,我将代码修改为上面的代码;采用 here 的建议,其中 << 实现是在 boost::detail::has_left_shift_impl 命名空间内定义的。唉,我现在面临另一个错误:

/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)。

相反您可以使用值转换属性映射(当然是只读的):

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))

Live On Coliru

#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}"];
}

关于c++ - 为 GraphViz 的 Boost Graph 捆绑输出重载流运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29947535/

相关文章:

c++ - boost deadline_timer 最小示例 : should I substitute "sleep"?

java - Boost unordered_map 是否仅适用于将项目与整数相关联?

c++ - C++ 中的递归合并排序示例

c++ - 延迟函数调用,如何传递参数?

c++ - 带有 char 数组的 Ifstream

Graphviz:如何使子图节点成一直线排列?

scikit-learn - 绘制决策树,graphvizm pydotplus

C++多态构造函数错误;标识符未定义

c++ - 服务器应用程序框架(最好使用 BOOST C++)

python - Pycharm 的 PygraphViz 导入错误