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..a26f7b8ba 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,16 @@ 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; + }; + + template < typename T > + struct unwrap_reference_wrapper > { + typedef T& type; + }; + /*! * @internal * Algorithm finding all the cycles starting from a given vertex. @@ -313,8 +324,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..6c9a74254 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,18 @@ 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&) + { + + } +}; + int main() { // The last two arguments to cycle_test() are the expected (correct) @@ -62,6 +76,24 @@ int main() cycle_test(call_hawick_unique_circuits(ml), nc3[ml], nc4[ml]); } + // Make sure we can pass a reference_wrapper to the algorithm. + { + 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)); + } + std::cout << "\n\n"; return boost::report_errors(); }