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

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

问题

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

  1. auto [it1, it2] = out_edges(u, _graph);
  2. 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'
我不明白这个错误,也不知道我应该如何定义所需的扣除指南。

迭代器类型

迭代器类型如下:

  1. class out_edge_iterator
  2. : public boost::iterator_adaptor<out_edge_iterator,
  3. vertex_descriptor const *,
  4. edge_descriptor,
  5. forward_traversal_tag,
  6. edge_descriptor>
  7. {
  8. vertex_descriptor const *last;
  9. vertex_descriptor source;
  10. public:
  11. out_edge_iterator(Vertex const *first, Vertex const *last, Vertex source)
  12. : out_edge_iterator::iterator_adaptor_(first), last(last),
  13. source(source)
  14. {
  15. BOOST_ASSERT(source != null_vertex());
  16. post_increment();
  17. }
  18. private:
  19. edge_descriptor dereference() const
  20. {
  21. return edge_descriptor(source, *this->base_reference());
  22. }
  23. void post_increment()
  24. {
  25. while (this->base_reference() != last
  26. && *this->base_reference() == null_vertex())
  27. {
  28. this->base_reference()++;
  29. }
  30. }
  31. void increment()
  32. {
  33. this->base_reference()++;
  34. post_increment();
  35. }
  36. friend class boost::iterator_core_access;
  37. };

配置:

  • 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

  1. #include <boost/graph/adjacency_list.hpp>
  2. #include <iostream>
  3. using Graph = boost::adjacency_list<boost::listS, boost::vecS, boost::directedS>;
  4. int main() {
  5. Graph g;
  6. add_edge(0, 1, g);
  7. add_edge(1, 2, g);
  8. add_edge(1, 3, g);
  9. add_edge(1, 4, g);
  10. add_edge(2, 5, g);
  11. add_edge(3, 6, g);
  12. for (auto v : boost::make_iterator_range(vertices(g))) {
  13. std::cout << v << " ->";
  14. for (auto e : make_iterator_range(out_edges(v, g))) {
  15. std::cout << " " << e;
  16. }
  17. std::cout << "\n";
  18. }
  19. }

有时候你可能需要

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

std::ranges

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

Live On Coliru

  1. #include <boost/graph/adjacency_list.hpp>
  2. #include <iostream>
  3. #include <ranges>
  4. using Graph = boost::adjacency_list<boost::listS, boost::vecS, boost::directedS>;
  5. int main() {
  6. Graph g;
  7. add_edge(0, 1, g);
  8. add_edge(1, 2, g);
  9. add_edge(1, 3, g);
  10. add_edge(1, 4, g);
  11. add_edge(2, 5, g);
  12. add_edge(3, 6, g);
  13. auto [vb,ve] = vertices(g);
  14. for (auto v : std::ranges::subrange(vb, ve)) {
  15. std::cout << v << " ->";
  16. auto [eb, ee] = out_edges(v, g);
  17. for (auto e : std::ranges::subrange(eb, ee)) {
  18. std::cout << " " << e;
  19. }
  20. std::cout << "\n";
  21. }
  22. }

Range-V3

Live On Compiler Explorer

  1. #include <boost/graph/adjacency_list.hpp>
  2. #include <iostream>
  3. #include <range/v3/all.hpp>
  4. namespace r = ::ranges::v3;
  5. using Graph = boost::adjacency_list<boost::listS, boost::vecS, boost::directedS>;
  6. int main() {
  7. Graph g;
  8. add_edge(0, 1, g);
  9. add_edge(1, 2, g);
  10. add_edge(1, 3, g);
  11. add_edge(1, 4, g);
  12. add_edge(2, 5, g);
  13. add_edge(3, 6, g);
  14. auto [vb,ve] = vertices(g);
  15. for (auto v : r::subrange(vb, ve)) {
  16. std::cout << v << " ->";
  17. auto [eb, ee] = out_edges(v, g);
  18. for (auto e : r::subrange(eb, ee)) {
  19. std::cout << " " << e;
  20. }
  21. std::cout << "\n";
  22. }
  23. }

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

  1. 0 -> (0,1)
  2. 1 -> (1,2) (1,3) (1,4)
  3. 2 -> (2,5)
  4. 3 -> (3,6)
  5. 4 ->
  6. 5 ->
  7. 6 ->
展开查看全部

相关问题