From c0ac114abf08b38220319ed2ffa6e28b06718386 Mon Sep 17 00:00:00 2001 From: kdeweese Date: Wed, 28 Aug 2024 15:47:00 -0700 Subject: [PATCH 1/3] change cc dfs to bfs for better performance --- include/graph/algorithm/connected_components.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/graph/algorithm/connected_components.hpp b/include/graph/algorithm/connected_components.hpp index bbc45ad..55194af 100644 --- a/include/graph/algorithm/connected_components.hpp +++ b/include/graph/algorithm/connected_components.hpp @@ -17,7 +17,7 @@ #include "graph/graph.hpp" #include "graph/views/incidence.hpp" #include "graph/views/vertexlist.hpp" -#include "graph/views/depth_first_search.hpp" +#include "graph/views/breadth_first_search.hpp" #include #ifndef GRAPH_CC_HPP @@ -102,8 +102,8 @@ void connected_components(G&& g, // graph } visited[uid] = true; component[uid] = cid; - vertices_depth_first_search_view dfs(g, uid); - for (auto&& [vid, v] : dfs) { + vertices_breadth_first_search_view bfs(g, uid); + for (auto&& [vid, v] : bfs) { component[vid] = cid; visited[vid] = true; } From 0e75c30c6ede3f1aebd70651d2da1fa7edd4ce8e Mon Sep 17 00:00:00 2001 From: kdeweese Date: Wed, 28 Aug 2024 15:52:43 -0700 Subject: [PATCH 2/3] missing header --- include/graph/algorithm/connected_components.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/graph/algorithm/connected_components.hpp b/include/graph/algorithm/connected_components.hpp index 55194af..f87c505 100644 --- a/include/graph/algorithm/connected_components.hpp +++ b/include/graph/algorithm/connected_components.hpp @@ -18,6 +18,7 @@ #include "graph/views/incidence.hpp" #include "graph/views/vertexlist.hpp" #include "graph/views/breadth_first_search.hpp" +#include "graph/views/depth_first_search.hpp" #include #ifndef GRAPH_CC_HPP From 2ae7e9714839062b78adc9a30f79600f04d3eb2c Mon Sep 17 00:00:00 2001 From: pratzl Date: Mon, 2 Sep 2024 21:15:01 +0000 Subject: [PATCH 3/3] :octocat: Applied clang-format. --- example/CppCon2021/include/dijkstra.hpp | 2 +- example/CppCon2021/include/utilities.hpp | 10 +-- example/CppCon2022/germany_routes_example.cpp | 4 +- example/CppCon2022/graphviz_output.hpp | 4 +- example/CppCon2022/rr_adaptor.hpp | 4 +- .../graph/algorithm/depth_first_search.hpp | 14 ++-- include/graph/container/compressed_graph.hpp | 24 +++--- include/graph/container/dynamic_graph.hpp | 8 +- include/graph/detail/graph_cpo.hpp | 81 ++++++++++--------- include/graph/graph.hpp | 2 +- include/graph/views/breadth_first_search.hpp | 16 ++-- include/graph/views/depth_first_search.hpp | 16 ++-- include/graph/views/edgelist.hpp | 18 ++--- tests/csv_routes.hpp | 9 +-- tests/depth_first_search_tests.cpp | 17 ++-- tests/edgelist_tests.cpp | 10 +-- 16 files changed, 119 insertions(+), 120 deletions(-) diff --git a/example/CppCon2021/include/dijkstra.hpp b/example/CppCon2021/include/dijkstra.hpp index bf920ae..c9d8c5a 100644 --- a/example/CppCon2021/include/dijkstra.hpp +++ b/example/CppCon2021/include/dijkstra.hpp @@ -20,7 +20,7 @@ #include #include -template > WeightFunction = std::function>(const inner_value_t&)>> auto dijkstra( diff --git a/example/CppCon2021/include/utilities.hpp b/example/CppCon2021/include/utilities.hpp index fc66e8f..0cb4908 100644 --- a/example/CppCon2021/include/utilities.hpp +++ b/example/CppCon2021/include/utilities.hpp @@ -151,7 +151,7 @@ auto make_index_edges(M& map, const E& edges) { */ template >> + graph::basic_adjacency_list Graph = std::vector>> auto make_plain_graph(const V& vertices, const E& edges, bool directed = true, size_t idx = 0) { auto vertex_map = make_index_map(vertices); auto index_edges = make_plain_edges(vertex_map, edges); @@ -167,7 +167,7 @@ auto make_plain_graph(const V& vertices, const E& edges, bool directed = true, s */ template >>> + graph::basic_adjacency_list Graph = std::vector>>> auto make_index_graph(const V& vertices, const E& edges, bool directed = true, size_t idx = 0) { auto vertex_map = make_index_map(vertices); @@ -185,7 +185,7 @@ auto make_index_graph(const V& vertices, const E& edges, bool directed = true, s */ template >> auto make_property_graph(const V& vertices, const E& edges, bool directed = true, size_t idx = 0) { @@ -226,7 +226,7 @@ auto data_to_graph_edge_list(const V& left_vertices, const V& right_vertices, co template >> auto make_plain_bipartite_graph(const V1& left_vertices, const V2& right_vertices, const E& edges, size_t idx = 0) { @@ -273,7 +273,7 @@ auto make_bipartite_graph(const V& left_vertices, const V& right_vertices, const template >> auto make_bipartite_graphs(const V& left_vertices, const V& right_vertices, const E& edges) { diff --git a/example/CppCon2022/germany_routes_example.cpp b/example/CppCon2022/germany_routes_example.cpp index afcc49a..e42ee79 100644 --- a/example/CppCon2022/germany_routes_example.cpp +++ b/example/CppCon2022/germany_routes_example.cpp @@ -103,8 +103,8 @@ TEST_CASE("Germany Routes Presentation", "[presentation][germany][routes][shorte vertex_reference_t frankfurt = *find_vertex(g, frankfurt_id); cout << "Traverse the vertices & outgoing edges" << endl; - for (auto&& [uid, u] : vertexlist(g)) { // [id,vertex&] - cout << city_id(g, uid) << endl; // city name [id] + for (auto&& [uid, u] : vertexlist(g)) { // [id,vertex&] + cout << city_id(g, uid) << endl; // city name [id] for (auto&& [vid, uv] : graph::views::incidence(g, uid)) { // [target_id,edge&] cout << " --> " << city_id(g, vid) << endl; // "--> "target city" [target_id] diff --git a/example/CppCon2022/graphviz_output.hpp b/example/CppCon2022/graphviz_output.hpp index b70df1b..139bc2a 100644 --- a/example/CppCon2022/graphviz_output.hpp +++ b/example/CppCon2022/graphviz_output.hpp @@ -108,8 +108,8 @@ void output_routes_graphviz_adjlist( template void output_routes_graphviz_dfs_vertices( - G& g, - std::string_view filename, + G& g, + std::string_view filename, graph::vertex_id_t seed, std::string_view bgcolor = std::string_view() // "transparent" or see http://graphviz.org/docs/attr-types/color/ ) { diff --git a/example/CppCon2022/rr_adaptor.hpp b/example/CppCon2022/rr_adaptor.hpp index b310a8d..4f1975c 100644 --- a/example/CppCon2022/rr_adaptor.hpp +++ b/example/CppCon2022/rr_adaptor.hpp @@ -105,8 +105,8 @@ class rr_adaptor { using edge_type = std::ranges::range_value_t; // using vertex_id_type = std::remove_cv_t>>; using edge_value_type = std::conditional_t<(std::tuple_size_v> <= 1), - void, - std::tuple_element_t<1, to_tuple_t>>; + void, + std::tuple_element_t<1, to_tuple_t>>; using vertex_value_type = std::ranges::range_value_t; public: diff --git a/include/graph/algorithm/depth_first_search.hpp b/include/graph/algorithm/depth_first_search.hpp index 8dd65a0..6584d2e 100644 --- a/include/graph/algorithm/depth_first_search.hpp +++ b/include/graph/algorithm/depth_first_search.hpp @@ -98,16 +98,16 @@ inline void init_dfs(Distances& distances, Predecessors& predecessors) { */ // C++ -inline void -depth_first_search(const Graph& g, const Source& source, Distances& distances, Predecessors& predecessors) {} +inline void depth_first_search(const Graph& g, const Source& source, Distances& distances, Predecessors& predecessors) { +} // C inline void depth_first_search(const Graph* g, - const Source source, - const size_t distances_len, - Distances* distances, - const size_t predecessors_len, - Predecessors* predecessors) {} + const Source source, + const size_t distances_len, + Distances* distances, + const size_t predecessors_len, + Predecessors* predecessors) {} } // namespace graph diff --git a/include/graph/container/compressed_graph.hpp b/include/graph/container/compressed_graph.hpp index db0d832..e35bd69 100644 --- a/include/graph/container/compressed_graph.hpp +++ b/include/graph/container/compressed_graph.hpp @@ -233,7 +233,7 @@ class csr_row_values { using value_type = void; using size_type = size_t; //VId; -public: // Properties +public: // Properties [[nodiscard]] constexpr size_type size() const noexcept { return 0; } [[nodiscard]] constexpr bool empty() const noexcept { return true; } [[nodiscard]] constexpr size_type capacity() const noexcept { return 0; } @@ -345,7 +345,7 @@ class csr_col_values { using value_type = void; using size_type = size_t; //VId; -public: // Properties +public: // Properties [[nodiscard]] constexpr size_type size() const noexcept { return 0; } [[nodiscard]] constexpr bool empty() const noexcept { return true; } [[nodiscard]] constexpr size_type capacity() const noexcept { return 0; } @@ -519,7 +519,7 @@ class compressed_graph_base } public: -public: // Operations +public: // Operations void reserve_vertices(size_type count) { row_index_.reserve(count + 1); // +1 for terminating row row_values_base::reserve(count); @@ -631,8 +631,8 @@ class compressed_graph_base // We can get the last vertex id from the list because erng is required to be ordered by // the source id. It's possible a target_id could have a larger id also, which is taken // care of at the end of this function. - vertex_count = max(vertex_count, - static_cast(last_erng_id(erng, eprojection) + 1)); // +1 for zero-based index + vertex_count = + max(vertex_count, static_cast(last_erng_id(erng, eprojection) + 1)); // +1 for zero-based index reserve_vertices(vertex_count); // Eval number of input rows and reserve space for the edges, if possible @@ -684,8 +684,8 @@ class compressed_graph_base // We can get the last vertex id from the list because erng is required to be ordered by // the source id. It's possible a target_id could have a larger id also, which is taken // care of at the end of this function. - vertex_count = max(vertex_count, - static_cast(last_erng_id(erng, eprojection) + 1)); // +1 for zero-based index + vertex_count = + max(vertex_count, static_cast(last_erng_id(erng, eprojection) + 1)); // +1 for zero-based index reserve_vertices(vertex_count); // Eval number of input rows and reserve space for the edges, if possible @@ -813,13 +813,13 @@ class compressed_graph_base private: // CPO properties friend constexpr vertices_type vertices(compressed_graph_base& g) { if (g.row_index_.empty()) - return vertices_type(g.row_index_); // really empty + return vertices_type(g.row_index_); // really empty else return vertices_type(g.row_index_.begin(), g.row_index_.end() - 1); // don't include terminating row } friend constexpr const_vertices_type vertices(const compressed_graph_base& g) { if (g.row_index_.empty()) - return const_vertices_type(g.row_index_); // really empty + return const_vertices_type(g.row_index_); // really empty else return const_vertices_type(g.row_index_.begin(), g.row_index_.end() - 1); // don't include terminating row } @@ -836,7 +836,7 @@ class compressed_graph_base friend constexpr edges_type edges(graph_type& g, vertex_type& u) { static_assert(contiguous_range, "row_index_ must be a contiguous range to get next row"); vertex_type* u2 = &u + 1; - assert(static_cast(u2 - &u) < g.row_index_.size()); // in row_index_ bounds? + assert(static_cast(u2 - &u) < g.row_index_.size()); // in row_index_ bounds? assert(static_cast(u.index) <= g.col_index_.size() && static_cast(u2->index) <= g.col_index_.size()); // in col_index_ bounds? return edges_type(g.col_index_.begin() + u.index, g.col_index_.begin() + u2->index); @@ -844,7 +844,7 @@ class compressed_graph_base friend constexpr const_edges_type edges(const graph_type& g, const vertex_type& u) { static_assert(contiguous_range, "row_index_ must be a contiguous range to get next row"); const vertex_type* u2 = &u + 1; - assert(static_cast(u2 - &u) < g.row_index_.size()); // in row_index_ bounds? + assert(static_cast(u2 - &u) < g.row_index_.size()); // in row_index_ bounds? assert(static_cast(u.index) <= g.col_index_.size() && static_cast(u2->index) <= g.col_index_.size()); // in col_index_ bounds? return const_edges_type(g.col_index_.begin() + u.index, g.col_index_.begin() + u2->index); @@ -853,7 +853,7 @@ class compressed_graph_base friend constexpr edges_type edges(graph_type& g, const vertex_id_type uid) { assert(static_cast(uid + 1) < g.row_index_.size()); // in row_index_ bounds? assert(static_cast(g.row_index_[static_cast(uid) + 1].index) <= - g.col_index_.size()); // in col_index_ bounds? + g.col_index_.size()); // in col_index_ bounds? return edges_type(g.col_index_.begin() + g.row_index_[static_cast(uid)].index, g.col_index_.begin() + g.row_index_[static_cast(uid + 1)].index); } diff --git a/include/graph/container/dynamic_graph.hpp b/include/graph/container/dynamic_graph.hpp index 1f51f7f..5051251 100644 --- a/include/graph/container/dynamic_graph.hpp +++ b/include/graph/container/dynamic_graph.hpp @@ -1256,7 +1256,7 @@ class dynamic_graph_base { constexpr typename vertices_type::value_type& operator[](size_type i) noexcept { return vertices_[i]; } constexpr const typename vertices_type::value_type& operator[](size_type i) const noexcept { return vertices_[i]; } -public: // Operations +public: // Operations void reserve_vertices(size_type count) { if constexpr (reservable) // reserve if we can; otherwise ignored vertices_.reserve(count); @@ -1273,13 +1273,13 @@ class dynamic_graph_base { // ignored for this graph; may be meaningful for another data structure like CSR } -private: // Member Variables +private: // Member Variables vertices_type vertices_; partition_vector partition_; // partition_[n] holds the first vertex id for each partition n // holds +1 extra terminating partition size_t edge_count_ = 0; // total number of edges in the graph -private: // CPO properties +private: // CPO properties friend constexpr vertices_type& vertices(dynamic_graph_base& g) { return g.vertices_; } friend constexpr const vertices_type& vertices(const dynamic_graph_base& g) { return g.vertices_; } @@ -1735,7 +1735,7 @@ class dynamic_graph : public dynamic_graph_base in msvc. struct _Decay_copy final { template - constexpr std::decay_t<_Tp> operator()(_Tp&& __t) const noexcept(std::is_nothrow_convertible_v<_Tp, std::decay_t<_Tp>>) { + constexpr std::decay_t<_Tp> operator()(_Tp&& __t) const + noexcept(std::is_nothrow_convertible_v<_Tp, std::decay_t<_Tp>>) { return std::forward<_Tp>(__t); } } inline constexpr _Fake_copy_init{}; @@ -191,7 +192,7 @@ namespace _Vertices { { _Fake_copy_init(__g.vertices()) }; }; template - concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // + concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g) { { _Fake_copy_init(vertices(__g)) }; // intentional ADL }; @@ -243,7 +244,7 @@ namespace _Vertices { return __g.vertices(); } else if constexpr (_Strat_ref == _St_ref::_Non_member) { //static_assert(is_reference_v); - return vertices(__g); // intentional ADL + return vertices(__g); // intentional ADL } else if constexpr (_Strat_ref == _St_ref::_Auto_eval) { return std::forward<_G>(__g); // intentional ADL } else { @@ -302,7 +303,7 @@ namespace _Vertex_id { { _Fake_copy_init(ui->vertex_id(__g)) }; }; template - concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // + concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g, const vertex_iterator_t<_G> ui) { { _Fake_copy_init(vertex_id(__g, ui)) }; // intentional ADL }; @@ -479,7 +480,7 @@ namespace _Find_vertex { }; template - concept _Has_ADL = _Has_class_or_enum_type<_G> // + concept _Has_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g, const vertex_id_t<_G>& uid) { { _Fake_copy_init(find_vertex(__g, uid)) }; // intentional ADL }; @@ -566,7 +567,7 @@ namespace _Edges { { _Fake_copy_init(u.edges(__g)) }; }; template - concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // + concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g, const vertex_reference_t<_G>& u) { { _Fake_copy_init(edges(__g, u)) }; // intentional ADL }; @@ -574,7 +575,7 @@ namespace _Edges { concept _Can_ref_eval = _Has_class_or_enum_type<_G> && forward_range>; template - concept _Has_id_ADL = _Has_class_or_enum_type<_G> // + concept _Has_id_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g, const vertex_id_t<_G>& uid) { { _Fake_copy_init(edges(__g, uid)) }; // intentional ADL }; @@ -649,7 +650,7 @@ namespace _Edges { } else if constexpr (_Strat_ref == _St_ref::_Non_member) { return edges(__g, u); // intentional ADL } else if constexpr (_Strat_ref == _St_ref::_Auto_eval) { - return u; // default impl + return u; // default impl } else { static_assert(_Always_false<_G>, "edges(g,u) is not defined and the default implementation cannot be evaluated"); @@ -675,7 +676,7 @@ namespace _Edges { constexpr _St_id _Strat_id = _Choice_id<_G&>._Strategy; if constexpr (_Strat_id == _St_id::_Non_member) { - return edges(__g, uid); // intentional ADL + return edges(__g, uid); // intentional ADL } else if constexpr (_Strat_id == _St_id::_Auto_eval) { return *find_vertex(__g, uid); // default impl } else { @@ -735,7 +736,7 @@ namespace _NumEdges { { _Fake_copy_init(__g.num_edges()) }; }; template - concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // + concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g) { { _Fake_copy_init(num_edges(__g)) }; // intentional ADL }; @@ -1023,7 +1024,7 @@ namespace _Source_id { { _Fake_copy_init(uv.source_id(__g)) }; }; template - concept _Has_adjl_ref_ADL = _Has_class_or_enum_type<_G> // + concept _Has_adjl_ref_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g, const edge_reference_t<_G>& uv) { { _Fake_copy_init(source_id(__g, uv)) }; // intentional ADL }; @@ -1033,7 +1034,7 @@ namespace _Source_id { { _Fake_copy_init(__e.source_id()) }; }; template - concept _Has_edgl_ref_ADL = _Has_class_or_enum_type<_E> // + concept _Has_edgl_ref_ADL = _Has_class_or_enum_type<_E> // && requires(_E&& __e) { { _Fake_copy_init(source_id(__e)) }; // intentional ADL }; @@ -1142,7 +1143,7 @@ namespace _Source_id { } else if constexpr (_Strat_ref == _St_edgl_ref::_Non_member) { return source_id(__e); // intentional ADL } else if constexpr (_Strat_ref == _St_edgl_ref::_Tuple_id) { - return get<1>(__e); // first element of tuple/pair + return get<1>(__e); // first element of tuple/pair } else if constexpr (_Strat_ref == _St_edgl_ref::_EDesc_id) { return __e.source_id; } else { @@ -1179,7 +1180,7 @@ namespace _Target { # endif // ^^^ workaround ^^^ template - concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // + concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g, const edge_reference_t<_G>& uv) { { _Fake_copy_init(target(__g, uv)) }; // intentional ADL }; @@ -1263,7 +1264,7 @@ namespace _Source { # endif // ^^^ workaround ^^^ template - concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // + concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g, const edge_reference_t<_G>& uv) { { _Fake_copy_init(source(__g, uv)) }; // intentional ADL }; @@ -1356,7 +1357,7 @@ namespace _Find_vertex_edge { }; template - concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // + concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g, vertex_reference_t<_G> u, const vertex_id_t<_G>& vid) { { _Fake_copy_init(find_vertex_edge(__g, u, vid)) }; // intentional ADL }; @@ -1367,7 +1368,7 @@ namespace _Find_vertex_edge { }; template - concept _Has_id_ADL = _Has_class_or_enum_type<_G> // + concept _Has_id_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g, vertex_id_t<_G> uid, const vertex_id_t<_G>& vid) { { _Fake_copy_init(find_vertex_edge(__g, uid, vid)) }; // intentional ADL }; @@ -1504,7 +1505,7 @@ namespace _Contains_edge { # endif // ^^^ workaround ^^^ template - concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // + concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g, const vertex_id_t<_G>& uid, const vertex_id_t<_G>& vid) { { _Fake_copy_init(contains_edge(__g, uid, vid)) }; // intentional ADL }; @@ -1603,7 +1604,7 @@ namespace _Partition_id { { _Fake_copy_init(u.partition_id(__g)) }; }; template - concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // + concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g, const vertex_reference_t<_G>& u) { { _Fake_copy_init(partition_id(__g, u)) }; // intentional ADL }; @@ -1614,7 +1615,7 @@ namespace _Partition_id { }; template - concept _Has_id_ADL = _Has_class_or_enum_type<_G> // + concept _Has_id_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g, const vertex_id_t<_G>& uid) { { _Fake_copy_init(partition_id(__g, uid)) }; // intentional ADL }; @@ -1636,7 +1637,7 @@ namespace _Partition_id { return {_St_id::_Non_member, noexcept(_Fake_copy_init(partition_id(declval<_G>(), declval>())))}; // intentional ADL } else if constexpr (_Can_id_eval<_G>) { - return {_St_id::_Auto_eval, noexcept(_Fake_copy_init(vertex_id_t<_G>(0)))}; // default impl + return {_St_id::_Auto_eval, noexcept(_Fake_copy_init(vertex_id_t<_G>(0)))}; // default impl } else { return {_St_id::_None}; } @@ -1688,7 +1689,7 @@ namespace _Partition_id { } else if constexpr (_Strat_ref == _St_ref::_Non_member) { return partition_id(__g, u); // intentional ADL } else if constexpr (_Strat_ref == _St_ref::_Auto_eval) { - return vertex_id_t<_G>{0}; // default impl + return vertex_id_t<_G>{0}; // default impl } else { static_assert(_Always_false<_G>, "partition_id(g,u) is not defined and the default implementation cannot be evaluated"); @@ -1716,7 +1717,7 @@ namespace _Partition_id { if constexpr (_Strat_id == _St_id::_Non_member) { return partition_id(__g, uid); // intentional ADL } else if constexpr (_Strat_id == _St_id::_Auto_eval) { - return vertex_id_t<_G>{0}; // default impl + return vertex_id_t<_G>{0}; // default impl } else { static_assert(_Always_false<_G>, "partition_id(g,uid) is not defined and the default implementation cannot be evaluated"); @@ -1749,7 +1750,7 @@ namespace _NumVertices { { _Fake_copy_init(__g.num_vertices(__g)) }; }; template - concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // + concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g) { { _Fake_copy_init(num_vertices(__g)) }; // intentional ADL }; @@ -1760,7 +1761,7 @@ namespace _NumVertices { }; template - concept _Has_id_ADL = _Has_class_or_enum_type<_G> // + concept _Has_id_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g, partition_id_t<_G> pid) { { _Fake_copy_init(num_vertices(__g, pid)) }; // intentional ADL }; @@ -1832,7 +1833,7 @@ namespace _NumVertices { static_assert(_Strat_id == _St_id::_Auto_eval); if constexpr (_Strat_id == _St_id::_Non_member) { - return num_vertices(__g, pid); // intentional ADL + return num_vertices(__g, pid); // intentional ADL } else if constexpr (_Strat_id == _St_id::_Auto_eval) { return size(vertices(__g, pid)); // default impl } else { @@ -1860,7 +1861,7 @@ namespace _NumVertices { if constexpr (_Strat_id == _St_ref::_Member) { return __g.num_vertices(); } else if constexpr (_Strat_id == _St_ref::_Non_member) { - return num_vertices(__g); // intentional ADL + return num_vertices(__g); // intentional ADL } else if constexpr (_Strat_id == _St_ref::_Auto_eval) { return size(vertices(__g)); // default impl } else { @@ -1891,7 +1892,7 @@ namespace _Degree { { _Fake_copy_init(u.degree(__g)) }; }; template - concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // + concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g, const vertex_reference_t<_G>& u) { { _Fake_copy_init(degree(__g, u)) }; // intentional ADL }; @@ -1902,7 +1903,7 @@ namespace _Degree { }; template - concept _Has_id_ADL = _Has_class_or_enum_type<_G> // + concept _Has_id_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g, const vertex_id_t<_G>& uid) { { _Fake_copy_init(degree(__g, uid)) }; // intentional ADL }; @@ -1975,7 +1976,7 @@ namespace _Degree { if constexpr (_Strat_ref == _St_ref::_Member) { return u.degree(__g); } else if constexpr (_Strat_ref == _St_ref::_Non_member) { - return degree(__g, u); // intentional ADL + return degree(__g, u); // intentional ADL } else if constexpr (_Strat_ref == _St_ref::_Auto_eval) { return size(edges(__g, u)); // default impl } else { @@ -2003,7 +2004,7 @@ namespace _Degree { constexpr _St_id _Strat_id = _Choice_id<_G&>._Strategy; if constexpr (_Strat_id == _St_id::_Non_member) { - return degree(__g, uid); // intentional ADL + return degree(__g, uid); // intentional ADL } else if constexpr (_Strat_id == _St_id::_Auto_eval) { return size(edges(__g, uid)); // default impl } else { @@ -2036,7 +2037,7 @@ namespace _Vertex_value { { _Fake_copy_init(u.vertex_value(__g)) }; }; template - concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // + concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g, vertex_reference_t<_G> u) { { _Fake_copy_init(vertex_value(__g, u)) }; // intentional ADL }; @@ -2116,7 +2117,7 @@ namespace _Edge_value { { _Fake_copy_init(uv.edge_value(__g)) }; }; template - concept _Has_adjl_ref_ADL = _Has_class_or_enum_type<_G> // + concept _Has_adjl_ref_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g, edge_reference_t<_G> uv) { { _Fake_copy_init(edge_value(__g, uv)) }; // intentional ADL }; @@ -2131,7 +2132,7 @@ namespace _Edge_value { { _Fake_copy_init(__e.edge_value()) }; }; template - concept _Has_edgl_ref_ADL = _Has_class_or_enum_type<_E> // + concept _Has_edgl_ref_ADL = _Has_class_or_enum_type<_E> // && requires(_E&& __e) { { _Fake_copy_init(edge_value(__e)) }; // intentional ADL }; @@ -2220,7 +2221,7 @@ namespace _Edge_value { } else if constexpr (_Strat_ref == _St_adjl_ref::_Non_member) { return edge_value(__g, uv); // intentional ADL } else if constexpr (_Strat_ref == _St_adjl_ref::_Auto_eval) { - return uv; // intentional ADL + return uv; // intentional ADL } else { static_assert(_Always_false<_G>, "edge_value(g,uv) must be defined for the graph"); } @@ -2249,7 +2250,7 @@ namespace _Edge_value { } else if constexpr (_Strat_ref == _St_edgl_ref::_Non_member) { return edge_value(__e); // intentional ADL } else if constexpr (_Strat_ref == _St_edgl_ref::_Tuple_id) { - return get<2>(__e); // first element of tuple/pair + return get<2>(__e); // first element of tuple/pair } else if constexpr (_Strat_ref == _St_edgl_ref::_EDesc_id) { return __e.value; } else { @@ -2296,7 +2297,7 @@ namespace _Graph_value { { _Fake_copy_init(__g.graph_value()) }; }; template - concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // + concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g) { { _Fake_copy_init(graph_value(__g)) }; // intentional ADL }; @@ -2368,7 +2369,7 @@ namespace _Num_partitions { { _Fake_copy_init(__g.num_partitions()) }; }; template - concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // + concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g) { { _Fake_copy_init(num_partitions(__g)) }; // intentional ADL }; @@ -2422,7 +2423,7 @@ namespace _Num_partitions { } else if constexpr (_Strat_ref == _St_ref::_Non_member) { return num_partitions(__g); // intentional ADL } else if constexpr (_Strat_ref == _St_ref::_Auto_eval) { - return vertex_id_t<_G>(1); // default impl + return vertex_id_t<_G>(1); // default impl } else { static_assert(_Always_false<_G>, "num_partitions(g) is not defined and the default implementation cannot be evaluated"); @@ -2452,7 +2453,7 @@ namespace _HasEdge { { _Fake_copy_init(__g.has_edge()) }; }; template - concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // + concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g) { { _Fake_copy_init(has_edge(__g)) }; // intentional ADL }; diff --git a/include/graph/graph.hpp b/include/graph/graph.hpp index 40b46b3..dcd8021 100644 --- a/include/graph/graph.hpp +++ b/include/graph/graph.hpp @@ -376,7 +376,7 @@ concept has_contains_edge = requires(G&& g, vertex_id_t uid, vertex_id_t v template struct define_unordered_edge : public std::false_type {}; // specialized for graph container edge -template // For exposition only +template // For exposition only concept unordered_edge = basic_sourced_edge && define_unordered_edge::value; // diff --git a/include/graph/views/breadth_first_search.hpp b/include/graph/views/breadth_first_search.hpp index 6c0eb98..871d86e 100644 --- a/include/graph/views/breadth_first_search.hpp +++ b/include/graph/views/breadth_first_search.hpp @@ -684,7 +684,7 @@ namespace views { # endif // ^^^ workaround ^^^ template - concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // + concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g, const vertex_id_t<_G>& uid, _Alloc alloc) { { _Fake_copy_init(vertices_breadth_first_search(__g, uid, alloc)) }; // intentional ADL }; @@ -771,7 +771,7 @@ namespace views { constexpr _St_ref _Strat_ref = _Choice_ref<_G&, _Alloc>._Strategy; if constexpr (_Strat_ref == _St_ref::_Non_member) { - return vertices_breadth_first_search(__g, seed, alloc); // intentional ADL + return vertices_breadth_first_search(__g, seed, alloc); // intentional ADL } else if constexpr (_Strat_ref == _St_ref::_Auto_eval) { return vertices_breadth_first_search_view<_G, void>(__g, seed, alloc); // default impl } else { @@ -804,7 +804,7 @@ namespace views { constexpr _St_ref_vvf _Strat_ref_vvf = _Choice_ref_vvf<_G&, _VVF, _Alloc>._Strategy; if constexpr (_Strat_ref_vvf == _St_ref_vvf::_Non_member) { - return vertices_breadth_first_search(__g, seed, vvf, alloc); // intentional ADL + return vertices_breadth_first_search(__g, seed, vvf, alloc); // intentional ADL } else if constexpr (_Strat_ref_vvf == _St_ref_vvf::_Auto_eval) { return vertices_breadth_first_search_view<_G, _VVF>(__g, seed, vvf, alloc); // default impl } else { @@ -833,7 +833,7 @@ namespace views { # endif // ^^^ workaround ^^^ template - concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // + concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g, const vertex_id_t<_G>& uid, _Alloc alloc) { { _Fake_copy_init(edges_breadth_first_search(__g, uid, alloc)) }; // intentional ADL }; @@ -922,7 +922,7 @@ namespace views { constexpr _St_ref _Strat_ref = _Choice_ref<_G&, _Alloc>._Strategy; if constexpr (_Strat_ref == _St_ref::_Non_member) { - return edges_breadth_first_search(__g, seed, alloc); // intentional ADL + return edges_breadth_first_search(__g, seed, alloc); // intentional ADL } else if constexpr (_Strat_ref == _St_ref::_Auto_eval) { return edges_breadth_first_search_view<_G, void, false>(__g, seed, alloc); // default impl } else { @@ -955,7 +955,7 @@ namespace views { constexpr _St_ref_evf _Strat_ref_evf = _Choice_ref_evf<_G&, _EVF, _Alloc>._Strategy; if constexpr (_Strat_ref_evf == _St_ref_evf::_Non_member) { - return edges_breadth_first_search(__g, seed, alloc); // intentional ADL + return edges_breadth_first_search(__g, seed, alloc); // intentional ADL } else if constexpr (_Strat_ref_evf == _St_ref_evf::_Auto_eval) { return edges_breadth_first_search_view<_G, _EVF, false>(__g, seed, evf, alloc); // default impl } else { @@ -1075,7 +1075,7 @@ namespace views { constexpr _St_ref _Strat_ref = _Choice_ref<_G&, _Alloc>._Strategy; if constexpr (_Strat_ref == _St_ref::_Non_member) { - return sourced_edges_breadth_first_search(__g, seed, alloc); // intentional ADL + return sourced_edges_breadth_first_search(__g, seed, alloc); // intentional ADL } else if constexpr (_Strat_ref == _St_ref::_Auto_eval) { return edges_breadth_first_search_view<_G, void, true>(__g, seed, alloc); // default impl } else { @@ -1108,7 +1108,7 @@ namespace views { constexpr _St_ref_evf _Strat_ref_evf = _Choice_ref_evf<_G&, _EVF, _Alloc>._Strategy; if constexpr (_Strat_ref_evf == _St_ref_evf::_Non_member) { - return sourced_edges_breadth_first_search(__g, seed, alloc); // intentional ADL + return sourced_edges_breadth_first_search(__g, seed, alloc); // intentional ADL } else if constexpr (_Strat_ref_evf == _St_ref_evf::_Auto_eval) { return edges_breadth_first_search_view<_G, _EVF, true>(__g, seed, evf, alloc); // default impl } else { diff --git a/include/graph/views/depth_first_search.hpp b/include/graph/views/depth_first_search.hpp index c3cb946..747d148 100644 --- a/include/graph/views/depth_first_search.hpp +++ b/include/graph/views/depth_first_search.hpp @@ -651,7 +651,7 @@ namespace views { # endif // ^^^ workaround ^^^ template - concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // + concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g, const vertex_id_t<_G>& uid, _Alloc alloc) { { _Fake_copy_init(vertices_depth_first_search(__g, uid, alloc)) }; // intentional ADL }; @@ -739,7 +739,7 @@ namespace views { constexpr _St_ref _Strat_ref = _Choice_ref<_G&, _Alloc>._Strategy; if constexpr (_Strat_ref == _St_ref::_Non_member) { - return vertices_depth_first_search(__g, seed, alloc); // intentional ADL + return vertices_depth_first_search(__g, seed, alloc); // intentional ADL } else if constexpr (_Strat_ref == _St_ref::_Auto_eval) { return vertices_depth_first_search_view<_G, void>(__g, seed, alloc); // default impl } else { @@ -772,7 +772,7 @@ namespace views { constexpr _St_ref_vvf _Strat_ref_vvf = _Choice_ref_vvf<_G&, _VVF, _Alloc>._Strategy; if constexpr (_Strat_ref_vvf == _St_ref_vvf::_Non_member) { - return vertices_depth_first_search(__g, seed, vvf, alloc); // intentional ADL + return vertices_depth_first_search(__g, seed, vvf, alloc); // intentional ADL } else if constexpr (_Strat_ref_vvf == _St_ref_vvf::_Auto_eval) { return vertices_depth_first_search_view<_G, _VVF>(__g, seed, vvf, alloc); // default impl } else { @@ -801,7 +801,7 @@ namespace views { # endif // ^^^ workaround ^^^ template - concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // + concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g, const vertex_id_t<_G>& uid, _Alloc alloc) { { _Fake_copy_init(edges_depth_first_search(__g, uid, alloc)) }; // intentional ADL }; @@ -890,7 +890,7 @@ namespace views { constexpr _St_ref _Strat_ref = _Choice_ref<_G&, _Alloc>._Strategy; if constexpr (_Strat_ref == _St_ref::_Non_member) { - return edges_depth_first_search(__g, seed, alloc); // intentional ADL + return edges_depth_first_search(__g, seed, alloc); // intentional ADL } else if constexpr (_Strat_ref == _St_ref::_Auto_eval) { return edges_depth_first_search_view<_G, void, false>(__g, seed, alloc); // default impl } else { @@ -923,7 +923,7 @@ namespace views { constexpr _St_ref_evf _Strat_ref_evf = _Choice_ref_evf<_G&, _EVF, _Alloc>._Strategy; if constexpr (_Strat_ref_evf == _St_ref_evf::_Non_member) { - return edges_depth_first_search(__g, seed, alloc); // intentional ADL + return edges_depth_first_search(__g, seed, alloc); // intentional ADL } else if constexpr (_Strat_ref_evf == _St_ref_evf::_Auto_eval) { return edges_depth_first_search_view<_G, _EVF, false>(__g, seed, evf, alloc); // default impl } else { @@ -1043,7 +1043,7 @@ namespace views { constexpr _St_ref _Strat_ref = _Choice_ref<_G&, _Alloc>._Strategy; if constexpr (_Strat_ref == _St_ref::_Non_member) { - return sourced_edges_depth_first_search(__g, seed, alloc); // intentional ADL + return sourced_edges_depth_first_search(__g, seed, alloc); // intentional ADL } else if constexpr (_Strat_ref == _St_ref::_Auto_eval) { return edges_depth_first_search_view<_G, void, true>(__g, seed, alloc); // default impl } else { @@ -1077,7 +1077,7 @@ namespace views { constexpr _St_ref_evf _Strat_ref_evf = _Choice_ref_evf<_G&, _EVF, _Alloc>._Strategy; if constexpr (_Strat_ref_evf == _St_ref_evf::_Non_member) { - return sourced_edges_depth_first_search(__g, seed, alloc); // intentional ADL + return sourced_edges_depth_first_search(__g, seed, alloc); // intentional ADL } else if constexpr (_Strat_ref_evf == _St_ref_evf::_Auto_eval) { return edges_depth_first_search_view<_G, _EVF, true>(__g, seed, evf, alloc); // default impl } else { diff --git a/include/graph/views/edgelist.hpp b/include/graph/views/edgelist.hpp index 513fd1b..2fa0a5f 100644 --- a/include/graph/views/edgelist.hpp +++ b/include/graph/views/edgelist.hpp @@ -392,7 +392,7 @@ namespace views { #endif // ^^^ workaround ^^^ template - concept _Has_adjlist_all_ADL = adjacency_list<_G> // + concept _Has_adjlist_all_ADL = adjacency_list<_G> // && requires(_G&& __g) { { _Fake_copy_init(edgelist(__g)) }; // intentional ADL }; @@ -402,14 +402,14 @@ namespace views { template concept _Has_adjlist_all_evf_ADL = adjacency_list<_G> && invocable> // && requires(_G&& __g, EVF evf) { - { _Fake_copy_init(edgelist(__g, evf)) }; // intentional ADL + { _Fake_copy_init(edgelist(__g, evf)) }; // intentional ADL }; template concept _Can_adjlist_all_evf_eval = adjacency_list<_G> && invocable>; template - concept _Has_adjlist_idrng_ADL = adjacency_list<_G> // + concept _Has_adjlist_idrng_ADL = adjacency_list<_G> // && requires(_G&& __g, vertex_id_t<_G> uid, vertex_id_t<_G> vid) { { _Fake_copy_init(edgelist(__g, uid, vid)) }; // intentional ADL }; @@ -417,8 +417,8 @@ namespace views { concept _Can_adjlist_idrng_eval = adjacency_list<_G>; template - concept _Has_adjlist_idrng_evf_ADL = adjacency_list<_G> // - && invocable> // + concept _Has_adjlist_idrng_evf_ADL = adjacency_list<_G> // + && invocable> // && requires(_G&& __g, vertex_id_t<_G> uid, vertex_id_t<_G> vid, EVF evf) { { _Fake_copy_init(edgelist(__g, uid, vid, evf)) }; // intentional ADL }; @@ -465,7 +465,7 @@ namespace views { return {_St_adjlist_all::_Non_member, noexcept(_Fake_copy_init(edgelist(declval<_G>(), declval())))}; // intentional ADL } else if constexpr (_Can_adjlist_all_evf_eval<_G, EVF>) { - return {_St_adjlist_all::_Auto_eval, noexcept(true)}; // default impl (revisit) + return {_St_adjlist_all::_Auto_eval, noexcept(true)}; // default impl (revisit) } else { return {_St_adjlist_all::_None}; } @@ -484,7 +484,7 @@ namespace views { noexcept(_Fake_copy_init(edgelist(declval<_G>(), declval>(), declval>())))}; // intentional ADL } else if constexpr (_Can_adjlist_idrng_eval<_G>) { - return {_St_adjlist_idrng::_Auto_eval, noexcept(true)}; // default impl (revisit) + return {_St_adjlist_idrng::_Auto_eval, noexcept(true)}; // default impl (revisit) } else { return {_St_adjlist_idrng::_None}; } @@ -520,7 +520,7 @@ namespace views { return {_St_edgelist_all::_Non_member, noexcept(_Fake_copy_init(edgelist(declval(), declval())))}; // intentional ADL } else if constexpr (_Can_edgelist_all_proj_eval) { - return {_St_edgelist_all::_Auto_eval, noexcept(true)}; // default impl (revisit) + return {_St_edgelist_all::_Auto_eval, noexcept(true)}; // default impl (revisit) } else { return {_St_edgelist_all::_None}; } @@ -703,7 +703,7 @@ namespace views { #endif //ENABLE_EDGELIST_RANGE }; // class _Cpo - } // namespace _Edgelist + } // namespace _Edgelist inline namespace _Cpos { inline constexpr _Edgelist::_Cpo edgelist; diff --git a/tests/csv_routes.hpp b/tests/csv_routes.hpp index 3ce3732..cd89275 100644 --- a/tests/csv_routes.hpp +++ b/tests/csv_routes.hpp @@ -178,7 +178,7 @@ std::optional> find_city(G&& g, std::string_view cit return std::optional>(); #else auto vertex_to_name = [&g](graph::vertex_reference_t u) { return graph::vertex_value(g, u); }; - auto it = std::ranges::lower_bound(graph::vertices(g), city_name, std::less(), vertex_to_name); + auto it = std::ranges::lower_bound(graph::vertices(g), city_name, std::less(), vertex_to_name); bool atEnd = (it == end(graph::vertices(g))); auto id = it - begin(graph::vertices(g)); if (it != end(graph::vertices(g)) && graph::vertex_value(g, *it) == city_name) @@ -198,8 +198,7 @@ graph::vertex_id_t find_city_id(G&& g, std::string_view city_name) { if (it != end(graph::vertices(g)) && graph::vertex_value(g, *it) != city_name) it = end(graph::vertices(g)); #endif - return static_cast>(it - - begin(graph::vertices(g))); // == size(vertices(g)) if not found + return static_cast>(it - begin(graph::vertices(g))); // == size(vertices(g)) if not found } /** @@ -574,8 +573,8 @@ void output_routes_graphviz_adjlist( template void output_routes_graphviz_dfs_vertices( - const G& g, - std::string_view filename, + const G& g, + std::string_view filename, graph::vertex_id_t seed, std::string_view bgcolor = std::string_view() // "transparent" or see http://graphviz.org/docs/attr-types/color/ ) { diff --git a/tests/depth_first_search_tests.cpp b/tests/depth_first_search_tests.cpp index 552ce60..3f174f3 100644 --- a/tests/depth_first_search_tests.cpp +++ b/tests/depth_first_search_tests.cpp @@ -4,10 +4,10 @@ #include "graph/container/dynamic_graph.hpp" #include -# define TEST_OPTION_OUTPUT (1) -# define TEST_OPTION_GEN (2) -# define TEST_OPTION_TEST (3) -# define TEST_OPTION TEST_OPTION_TEST +#define TEST_OPTION_OUTPUT (1) +#define TEST_OPTION_GEN (2) +#define TEST_OPTION_TEST (3) +#define TEST_OPTION TEST_OPTION_TEST using std::cout; using std::endl; @@ -29,19 +29,18 @@ TEST_CASE("depth_first_search algorithm test", "[bfs][single-source][algorithm]" REQUIRE(1 + 1 == 2); } -# if TEST_OPTION == TEST_OPTION_OUTPUT +#if TEST_OPTION == TEST_OPTION_OUTPUT SECTION("dfs algo output") { // output graph cout << "graph" << endl; } -# elif TEST_OPTION == TEST_OPTION_GEN +#elif TEST_OPTION == TEST_OPTION_GEN SECTION("dfs algo test generation") { // generate test code } -# elif TEST_OPTION == TEST_OPTION_TEST +#elif TEST_OPTION == TEST_OPTION_TEST SECTION("dfs algo test") { // production test code } -# endif // TEST_OPTION +#endif // TEST_OPTION } // TEST_CASE "depth_first_search algorithm test" - diff --git a/tests/edgelist_tests.cpp b/tests/edgelist_tests.cpp index 73639ad..30a09f1 100644 --- a/tests/edgelist_tests.cpp +++ b/tests/edgelist_tests.cpp @@ -31,7 +31,7 @@ TEST_CASE("edgelist tuple test", "[edgelist][tuple]") { } graph::_Target_id::_Cpo cpo; - E e; + E e; static_assert(same_as>); static_assert(!std::ranges::forward_range); @@ -63,7 +63,7 @@ TEST_CASE("edgelist tuple test with value", "[edgelist][tuple]") { } graph::_Target_id::_Cpo cpo; - E e; + E e; static_assert(same_as>); static_assert(!std::ranges::forward_range); @@ -101,7 +101,7 @@ TEST_CASE("edgelist pair test", "[edgelist][tuple]") { } graph::_Target_id::_Cpo cpo; - E e; + E e; static_assert(same_as>); static_assert(!std::ranges::forward_range); @@ -134,7 +134,7 @@ TEST_CASE("edgelist edge_descriptor test", "[edgelist][edge_descriptor]") { } graph::_Target_id::_Cpo cpo; - E e; + E e; static_assert(same_as>); static_assert(!std::ranges::forward_range); @@ -167,7 +167,7 @@ TEST_CASE("edgelist edge_descriptor test with value", "[edgelist][edge_descripto } graph::_Target_id::_Cpo cpo; - E e; + E e; static_assert(same_as>); static_assert(!std::ranges::forward_range);