c++ 在range-v3中,不能从两个迭代器创建子范围

kgsdhlau  于 2023-06-25  发布在  其他
关注(0)|答案(1)|浏览(132)

问题

我想从一个函数返回的两个迭代器创建一个范围。
我使用the answer to a related question创建了一个新的子范围,使用range-v3:

auto [it1, it2] = out_edges(u, _graph);
return  ranges::subrange(it1, it2) | ranges::views::transform([](auto it){return it->target();});

但是我的编译器告诉我:error: no viable constructor or deduction guide for deduction of template arguments of 'subrange'
我不明白这个错误,也不知道我应该如何定义所需的扣除指南。

迭代器类型

迭代器类型如下:

class out_edge_iterator
        : public boost::iterator_adaptor<out_edge_iterator,
                                         vertex_descriptor const *,
                                         edge_descriptor,
                                         forward_traversal_tag,
                                         edge_descriptor>
      {
        vertex_descriptor const *last;
        vertex_descriptor source;

      public:
        out_edge_iterator(Vertex const *first, Vertex const *last, Vertex source)
          : out_edge_iterator::iterator_adaptor_(first), last(last),
            source(source)
        {
          BOOST_ASSERT(source != null_vertex());
          post_increment();
        }

      private:
        edge_descriptor dereference() const
        {
          return edge_descriptor(source, *this->base_reference());
        }

        void post_increment()
        {
          while (this->base_reference() != last
                 && *this->base_reference() == null_vertex())
          {
            this->base_reference()++;
          }
        }

        void increment()
        {
          this->base_reference()++;
          post_increment();
        }

        friend class boost::iterator_core_access;
      };

配置:

  • Macos Ventura M1.
  • Apple clang版本14.0.3(clang-1403.0.22.14.1)
  • 目标:arm 64-apple-darwin 22.5.0
  • 螺纹型号:波西克斯
  • range-v3版本0.12.0
  • C++20
mjqavswn

mjqavswn1#

我有三个版本,只是使用Boost,使用std::ranges和使用Range-v3。
为了简化,我总是写boost::make_iterator_range(out_edges(e, g)),它工作得很好,可以把这对当作一个范围:

Just Boost

Live On Coliru

#include <boost/graph/adjacency_list.hpp>
#include <iostream>

using Graph = boost::adjacency_list<boost::listS, boost::vecS, boost::directedS>;

int main() {
    Graph g;

    add_edge(0, 1, g);
    add_edge(1, 2, g);
    add_edge(1, 3, g);
    add_edge(1, 4, g);
    add_edge(2, 5, g);
    add_edge(3, 6, g);

    for (auto v : boost::make_iterator_range(vertices(g))) {
        std::cout << v << " ->";
        for (auto e : make_iterator_range(out_edges(v, g))) {
            std::cout << " " << e;
        }
        std::cout << "\n";
    }
}

有时候你可能需要

#include <boost/range/iterator_range.hpp>`

std::ranges

在C++20中,可以使用std::ranges:

Live On Coliru

#include <boost/graph/adjacency_list.hpp>
#include <iostream>
#include <ranges>

using Graph = boost::adjacency_list<boost::listS, boost::vecS, boost::directedS>;

int main() {
    Graph g;

    add_edge(0, 1, g);
    add_edge(1, 2, g);
    add_edge(1, 3, g);
    add_edge(1, 4, g);
    add_edge(2, 5, g);
    add_edge(3, 6, g);

    auto [vb,ve] = vertices(g);
    for (auto v : std::ranges::subrange(vb, ve)) {
        std::cout << v << " ->";
        auto [eb, ee] = out_edges(v, g);
        for (auto e : std::ranges::subrange(eb, ee)) {
            std::cout << " " << e;
        }
        std::cout << "\n";
    }
}

Range-V3

Live On Compiler Explorer

#include <boost/graph/adjacency_list.hpp>
#include <iostream>
#include <range/v3/all.hpp>
namespace r = ::ranges::v3;

using Graph = boost::adjacency_list<boost::listS, boost::vecS, boost::directedS>;

int main() {
    Graph g;

    add_edge(0, 1, g);
    add_edge(1, 2, g);
    add_edge(1, 3, g);
    add_edge(1, 4, g);
    add_edge(2, 5, g);
    add_edge(3, 6, g);

    auto [vb,ve] = vertices(g);
    for (auto v : r::subrange(vb, ve)) {
        std::cout << v << " ->";
        auto [eb, ee] = out_edges(v, g);
        for (auto e : r::subrange(eb, ee)) {
            std::cout << " " << e;
        }
        std::cout << "\n";
    }
}

所有三个代码样本具有相同的输出:

0 -> (0,1)
1 -> (1,2) (1,3) (1,4)
2 -> (2,5)
3 -> (3,6)
4 ->
5 ->
6 ->

相关问题