From c63141b63f75c949d13c4b0091c1740437eb4c08 Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Wed, 14 Apr 2021 16:19:14 -0400 Subject: [PATCH 1/3] [hawick] Support passing std::reference_wrapper to boost::hawick_circuits Reported as ldionne/hawick_circuits#1. --- .../cycle_detection/hawick_circuits.adoc | 2 +- include/boost/graph/hawick_circuits.hpp | 16 ++++++++- test/hawick_circuits.cpp | 36 +++++++++++++++++++ 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/doc/modules/ROOT/pages/algorithms/cycle_detection/hawick_circuits.adoc b/doc/modules/ROOT/pages/algorithms/cycle_detection/hawick_circuits.adoc index 8b0bd7bf9..be2572252 100644 --- a/doc/modules/ROOT/pages/algorithms/cycle_detection/hawick_circuits.adoc +++ b/doc/modules/ROOT/pages/algorithms/cycle_detection/hawick_circuits.adoc @@ -120,4 +120,4 @@ The algorithm is described in detail in https://www.researchgate.net/publication == Notes * `hawick_circuits` enumerates all elementary circuits including redundant ones caused by parallel edges. Use `hawick_unique_circuits` to suppress those duplicates. -* The visitor is passed by value. If your visitor contains state, consider holding it by pointer or reference so that changes made during the algorithm are visible to the caller. +* The visitor is passed by value. If your visitor contains state, consider holding it by pointer or reference so that changes made during the algorithm are visible to the caller. If `visitor` is a `std::reference_wrapper`, it will be unwrapped before the `.cycle` method is called on it, which allows passing a visitor that shouldn't be copied. diff --git a/include/boost/graph/hawick_circuits.hpp b/include/boost/graph/hawick_circuits.hpp index 85a158bcf..5c796529e 100644 --- a/include/boost/graph/hawick_circuits.hpp +++ b/include/boost/graph/hawick_circuits.hpp @@ -20,6 +20,7 @@ #include // for boost::tie #include #include +#include // for std::reference_wrapper #include #include // for std::pair #include @@ -88,6 +89,18 @@ namespace hawick_circuits_detail return std::find(boost::begin(c), boost::end(c), v) != boost::end(c); } + template < typename T > + struct unwrap_reference_wrapper { + typedef T type; + }; + +#if __cplusplus >= 201103L + template < typename T > + struct unwrap_reference_wrapper > { + typedef T& type; + }; +#endif + /*! * @internal * Algorithm finding all the cycles starting from a given vertex. @@ -313,8 +326,9 @@ namespace hawick_circuits_detail typedef std::vector< Vertex > Stack; typedef std::vector< std::vector< Vertex > > ClosedMatrix; + typedef typename unwrap_reference_wrapper::type VisitorNoRef; - typedef hawick_circuits_from< Graph, Visitor, VertexIndexMap, Stack, + typedef hawick_circuits_from< Graph, VisitorNoRef, VertexIndexMap, Stack, ClosedMatrix, GetAdjacentVertices > SubAlgorithm; diff --git a/test/hawick_circuits.cpp b/test/hawick_circuits.cpp index c2fbe639c..7558050f9 100644 --- a/test/hawick_circuits.cpp +++ b/test/hawick_circuits.cpp @@ -6,6 +6,8 @@ #include "cycle_test.hpp" #include +#include +#include #include struct call_hawick_circuits @@ -32,6 +34,20 @@ struct call_hawick_unique_circuits } }; +struct not_copyable +{ + not_copyable() { } + + template < typename Path, typename Graph > + void cycle(Path const&, Graph const&) + { + + } + +private: + not_copyable(not_copyable const&); +}; + int main() { // The last two arguments to cycle_test() are the expected (correct) @@ -62,6 +78,26 @@ int main() cycle_test(call_hawick_unique_circuits(ml), nc3[ml], nc4[ml]); } + // Make sure we can pass a reference_wrapper to the algorithm. +#if __cplusplus >= 201103L + { + typedef boost::adjacency_list Graph; + typedef std::pair Pair; + Pair edges[3] = { + Pair(0, 1), // a->b + Pair(1, 2), // b->c + Pair(2, 0), // c->a + }; + + Graph G(3); + for (int i = 0; i < 3; ++i) + add_edge(edges[i].first, edges[i].second, G); + + not_copyable visitor; + boost::hawick_circuits(G, std::ref(visitor)); + } +#endif // >= C++11 + std::cout << "\n\n"; return boost::report_errors(); } From 8b0ad1300f1283f3bbf3f7e52813635645f3d8a8 Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Tue, 21 Jul 2026 08:14:01 -0400 Subject: [PATCH 2/3] Remove obsolete C++11 guards --- include/boost/graph/hawick_circuits.hpp | 2 -- test/hawick_circuits.cpp | 2 -- 2 files changed, 4 deletions(-) diff --git a/include/boost/graph/hawick_circuits.hpp b/include/boost/graph/hawick_circuits.hpp index 5c796529e..a26f7b8ba 100644 --- a/include/boost/graph/hawick_circuits.hpp +++ b/include/boost/graph/hawick_circuits.hpp @@ -94,12 +94,10 @@ namespace hawick_circuits_detail typedef T type; }; -#if __cplusplus >= 201103L template < typename T > struct unwrap_reference_wrapper > { typedef T& type; }; -#endif /*! * @internal diff --git a/test/hawick_circuits.cpp b/test/hawick_circuits.cpp index 7558050f9..e8157a636 100644 --- a/test/hawick_circuits.cpp +++ b/test/hawick_circuits.cpp @@ -79,7 +79,6 @@ int main() } // Make sure we can pass a reference_wrapper to the algorithm. -#if __cplusplus >= 201103L { typedef boost::adjacency_list Graph; typedef std::pair Pair; @@ -96,7 +95,6 @@ int main() not_copyable visitor; boost::hawick_circuits(G, std::ref(visitor)); } -#endif // >= C++11 std::cout << "\n\n"; return boost::report_errors(); From 81ac21073b7dd6235d4bbd3de2eac5c97fbaba72 Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Tue, 21 Jul 2026 08:15:19 -0400 Subject: [PATCH 3/3] use = delete --- test/hawick_circuits.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/hawick_circuits.cpp b/test/hawick_circuits.cpp index e8157a636..6c9a74254 100644 --- a/test/hawick_circuits.cpp +++ b/test/hawick_circuits.cpp @@ -37,15 +37,13 @@ struct call_hawick_unique_circuits struct not_copyable { not_copyable() { } + not_copyable(not_copyable const&) = delete; template < typename Path, typename Graph > void cycle(Path const&, Graph const&) { } - -private: - not_copyable(not_copyable const&); }; int main()