以直接方式迭代提升图中的捆绑属性
Posted
技术标签:
【中文标题】以直接方式迭代提升图中的捆绑属性【英文标题】:iterate over bundled properties in boost graph in a direct way 【发布时间】:2021-08-26 10:20:43 【问题描述】:我正在使用利用以下定义的 Boost 图形库
template <typename Vertex>
using graph = boost::adjacency_list<boost::listS,
boost::vecS,
boost::bidirectionalS,
Vertex>
template <typename Vertex>
using vertex = typename graph<Vertex>::vertex_descriptor;
模板参数Vertex
用于将BGL 与捆绑属性一起使用。
目前我对 boost 没有那么自信,我想了解是否有办法获得“捆绑属性列表”的 begin()
和 end()
迭代器。
换句话说,假设我有这个结构
struct City
string name;
int population;
vector<int> zipcodes;
;
我想将它用作我的图表的模板参数。我知道我可以像这样迭代顶点
(假设g
是我的邻接列表)
for(auto vd : boost::make_iterator_range(vertices(g))
auto v = g[*vd];
// do something with v
但我想这样做
for(auto & v : some_iterator)
// v is a city ...
有什么办法吗?
【问题讨论】:
请在以后编辑您现有的问题!通过删除另一个,您丢弃了我的答案文本。而且问题根本没有改变(尽管我看到了改进) 【参考方案1】:我已将my code from your now-deleted question 改编为更具体的示例。现在你已经意识到你实际上不是在迭代顶点,而是它们的包。
我建议您使用转换/间接迭代器适配器。我能想到的最简单的方法是使用 Boost Range Adaptors,特别是使用transformed
:
Live On Coliru
#include <boost/graph/adjacency_list.hpp>
#include <boost/range/adaptors.hpp>
using boost::adaptors::transformed;
template <typename Vertex> struct Wrapper
using graph = boost::adjacency_list<boost::listS, boost::vecS,
boost::bidirectionalS, Vertex>;
using vertex = typename graph::vertex_descriptor;
auto bundles()
auto accessor = [map = get(boost::vertex_bundle, _g)](vertex v) -> auto&
return map[v];
;
return vertices(_g) | transformed(accessor);
auto bundles() const
auto accessor = [map = get(boost::vertex_bundle, _g)](vertex v) -> auto&
return map[v];
;
return vertices(_g) | transformed(accessor);
private:
graph _g 5;
;
struct City
std::string name;
int population;
std::vector<int> zipcodes;
;
static int id_gen = 0;
struct Sample2 int id = ++id_gen; ;
#include <iostream>
#include <iomanip>
int main()
Wrapper<City> demo;
for (City& c : demo.bundles())
c.name = "name " + std::to_string(rand() % 100);
c.population = rand() % 128 * 190'000;
c.zipcodes = 1234, 2345;
auto const& const_ref = demo;
for (City const& c : const_ref.bundles())
std::cout << std::quoted(c.name) << ", population " << c.population << "\n";
打印
"name 83", population 13300000
"name 77", population 21850000
"name 93", population 24130000
"name 86", population 20520000
"name 49", population 14630000
【讨论】:
感谢您的回答。如果City
不可复制也不可移动怎么办?
那么你不能 - 根据定义 - 将它用作捆绑类型,因为它不符合存储要求documented。当然,您可以使用包装器(可选,一些智能指针或其他东西)来解决它,但如果您避免这种情况,通常使用库会更容易
再次感谢。最后一个问题:捆绑的属性存储在哪里?我不明白为什么我需要使用适配器将它们“打包”到新结构中。我一直在寻找一种方法来从 BGL 使用的结构化数据中获取迭代器来存储它们,但我对该库的理解还不够好
但是要响应更简单的“我不想返回vertices(g).first作为begin()或vertices(g).second作为end()” 请注意,我的答案正是您想要的。它不返回vertices(g).begin()
。相反,返回一个 transformed_range<Lambda, std::pair<VertexIterator> >
并在 lambda 中投影到包。当我编写老式的迭代器循环而不是 tanged-for: coliru.stacked-crooked.com/a/3fb14faffc439b14 时,它是否更清楚?
是的,最后一部分是我真正想要的,因为我现在可以在包装器的重载中返回 bundles().begin() 和 bundles().end()。我一开始就错过了那个信息。再次感谢!以上是关于以直接方式迭代提升图中的捆绑属性的主要内容,如果未能解决你的问题,请参考以下文章
Magento - 以编程方式添加的捆绑产品不适用于购物篮/前端