目标:
我想把一个Boost Graph封装到一个类中,这样我就有更多的控制权,减少main函数中的噪音,并打印一个graphviz格式。
问题
代码编译失败,返回include/boost/graph/detail/adjacency_list.hpp:2601:27: error: cannot form a reference to 'void'
最小可重现示例
代码在编译器资源管理器https://godbolt.org/z/9beKovxc9上编译,但如果取消注解main的最后一行,则会重现错误。
// BGL
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/visitors.hpp>
#include <boost/graph/breadth_first_search.hpp>
#include <boost/graph/graphviz.hpp>
#include <iostream> // std::cout
#include <functional> // std::function
#include <utility> // std::pair
///
/// @brief Defines the desired properties and constraints for a coalescent graph
///
struct tree_traits
{
///
/// @brief Trees are sparse graph in nature, adjacency_matrix would not be justified here
///
template<class... Types>
using implementation = boost::adjacency_list<Types...>;
///
/// @brief We want to enforce avoiding multi-graphs (edges with same end nodes)
///
using out_edge_list_type = boost::setS;
///
/// @brief We are prioritizing speed for space
///
using vertex_list_type = boost::listS;
///
/// @brief Coalescent trees are directed acyclic graphs
///
using directed_type = boost::directedS ;
}; // end tree_traits
///
/// @brief A graph with properties suited to represent a coalescent tree
///
template<class VertexProperties=boost::no_property, class EdgeProperties=boost::no_property>
class Tree
{
public:
///
/// @brief Properties of an edge, like the demes visited
/// @see https://www.boost.org/doc/libs/1_80_0/libs/graph/doc/bundles.html
///
using edge_properties = EdgeProperties;
///
/// @brief Properties of a vertex, like the mutational state
/// @see https://www.boost.org/doc/libs/1_80_0/libs/graph/doc/bundles.html
///
using vertex_properties = VertexProperties;
///
/// @brief The type of graph hold by the tree class
///
using graph_type = tree_traits::implementation
<
tree_traits::out_edge_list_type,
tree_traits::vertex_list_type,
tree_traits::directed_type,
VertexProperties,
EdgeProperties
>;
private:
graph_type _graph;
static constexpr bool vertex_prop_undefined = std::is_same<vertex_properties,boost::no_property>::value;
static constexpr bool edge_prop_undefined = std::is_same<edge_properties,boost::no_property>::value;
public:
/// @note adds an object-oriented layer
auto add_vertex(auto&&... args)
{
return boost::add_vertex(std::forward<decltype(args)>(args)..., _graph);
}
/// @note adds an object-oriented layer
/// @note order of vertices determines edge orientation
auto add_edge(auto&&... args)
{
return boost::add_edge(std::forward<decltype(args)>(args)..., _graph);
}
void to_graphviz(std::ostream& out) const
{
using namespace boost;
return boost::write_graphviz(out, _graph,
boost::make_label_writer(boost::get(vertex_bundle, this->_graph)),
boost::make_label_writer(boost::get(edge_bundle, this->_graph))
);
}
};
int main()
{
using q_tree_type = Tree<std::string, double>;
q_tree_type graph;
// We insert the root of tree
auto root = graph.add_vertex("first");
//graph.to_graphviz(std::cout); // <--- huho
}
□ □ □我能想到的
- 我认为(也许)使用纯
std::string
作为VertexProperties
而不是自定义结构会使编译器感到困惑。我试图消除与if constexpr
的歧义,如果VertexProperties
类型计算为no_property
,则使用default_writer
。但在这方面没有成功,但以下是我编写的令人尴尬的天真代码
// member of Tree<...> class
void to_graphviz(std::ostream& out) const
{
using namespace boost;
if constexpr (vertex_prop_undefined)
{
if constexpr (edge_prop_undefined)
return write_graphviz(out, _graph);
return boost::write_graphviz(out, _graph, default_writer(), boost::make_label_writer(boost::get(edge_bundle, this->_graph)));
}
if constexpr (edge_prop_undefined)
return write_graphviz(out, _graph, boost::make_label_writer(boost::get(vertex_bundle, this->_graph)));
return boost::write_graphviz(out, _graph, boost::make_label_writer(boost::get(vertex_bundle, this->_graph)), boost::make_label_writer(boost::get(edge_bundle, this->_graph)));
}
1条答案
按热度按时间btqmn9zl1#
您的问题与显示bundle无关。
std::string
和double
都是可输出流的,因此它们可以正常工作。你的问题是经典的:您选择的图表模型没有合适的隐式顶点索引。这是由于选择:
listS
的唯一原因是 *但是现在,让我们演示一下
write_graphviz
已经可以与vecS
一起工作了:**一个
图纸
变通方案?
我坚持使用
vecS
。Tree<>
的接口不允许插入顶点,除非在最后。您目前没有显示删除顶点的接口。这意味着重新分配成本和稳定性都不是首选listS
的原因。如果必须使用基于节点的顶点容器选择器,则需要为需要它的算法添加索引:
现场演示
也将其付诸实践:
**第一个e第一个f第一个x
图纸
注解
注意大多数算法需要顶点索引,例如
breadth_first_search
(你已经有了include for)requires it to create the default color map,你可以通过提供一个自定义的颜色Map表来解决这个问题,例如: