Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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.
14 changes: 13 additions & 1 deletion include/boost/graph/hawick_circuits.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <boost/tuple/tuple.hpp> // for boost::tie
#include <boost/type_traits/remove_reference.hpp>
#include <boost/utility/result_of.hpp>
#include <functional> // for std::reference_wrapper
#include <set>
#include <utility> // for std::pair
#include <vector>
Expand Down Expand Up @@ -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<std::reference_wrapper<T> > {
typedef T& type;
};

/*!
* @internal
* Algorithm finding all the cycles starting from a given vertex.
Expand Down Expand Up @@ -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<Visitor>::type VisitorNoRef;

typedef hawick_circuits_from< Graph, Visitor, VertexIndexMap, Stack,
typedef hawick_circuits_from< Graph, VisitorNoRef, VertexIndexMap, Stack,
ClosedMatrix, GetAdjacentVertices >
SubAlgorithm;

Expand Down
32 changes: 32 additions & 0 deletions test/hawick_circuits.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

#include "cycle_test.hpp"
#include <boost/graph/hawick_circuits.hpp>
#include <cstddef>
#include <functional>
#include <iostream>

struct call_hawick_circuits
Expand All @@ -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)
Expand Down Expand Up @@ -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<boost::vecS, boost::vecS, boost::directedS> Graph;
typedef std::pair<std::size_t, std::size_t> 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();
}
Loading