以直接方式迭代提升图中的捆绑属性

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&lt;Lambda, std::pair&lt;VertexIterator&gt; &gt; 并在 lambda 中投影到包。当我编写老式的迭代器循环而不是 tanged-for: coliru.stacked-crooked.com/a/3fb14faffc439b14 时,它是否更清楚? 是的,最后一部分是我真正想要的,因为我现在可以在包装器的重载中返回 bundles().begin() 和 bundles().end()。我一开始就错过了那个信息。再次感谢!

以上是关于以直接方式迭代提升图中的捆绑属性的主要内容,如果未能解决你的问题,请参考以下文章

OSGi:以编程方式决定是不是可以启动捆绑包

C++ 迭代器iterator的实现原理

为啥 JavaScript 中的对象不可迭代?

Magento - 以编程方式添加的捆绑产品不适用于购物篮/前端

如何自动删除 .properties 文件中捆绑资源中的所有重复属性键

如何以编程方式将因子捆绑与 browserify 一起使用?