13namespace graph_access_detail {
17 if constexpr (
requires { value.first; }) {
18 return static_cast<VertexId>(value.first);
31 { graph.vertex_count() } -> std::convertible_to<std::size_t>;
36 { vx_vertex_count(graph) } -> std::convertible_to<std::size_t>;
41 { graph.directed() } -> std::convertible_to<bool>;
46 { vx_is_directed(graph) } -> std::convertible_to<bool>;
51 { graph.version() } -> std::convertible_to<std::uint64_t>;
56 { vx_version(graph) } -> std::convertible_to<std::uint64_t>;
70template <ReadableGraph Graph>
71[[nodiscard]]
constexpr std::size_t
vertex_count(
const Graph& graph) {
73 return static_cast<std::size_t
>(graph.vertex_count());
75 return static_cast<std::size_t
>(vx_vertex_count(graph));
79template <ReadableGraph Graph>
82 return static_cast<bool>(graph.directed());
84 return static_cast<bool>(vx_is_directed(graph));
88template <MutableGraph Graph>
89[[nodiscard]]
constexpr std::uint64_t
graph_version(
const Graph& graph) {
91 return static_cast<std::uint64_t
>(graph.version());
93 return static_cast<std::uint64_t
>(vx_version(graph));
97template <ReadableGraph Graph,
class Fn>
99 if constexpr (
requires { graph.for_each_neighbor(u, std::forward<Fn>(fn)); }) {
100 graph.for_each_neighbor(u, std::forward<Fn>(fn));
101 }
else if constexpr (
requires { vx_for_each_neighbor(graph, u, std::forward<Fn>(fn)); }) {
102 vx_for_each_neighbor(graph, u, std::forward<Fn>(fn));
104 for (
const auto& neighbor : graph.neighbors(u)) {
110template <ReadableGraph Graph,
class Fn>
112 if constexpr (
requires { vx_for_each_weighted_neighbor(graph, u, std::forward<Fn>(fn)); }) {
113 vx_for_each_weighted_neighbor(graph, u, std::forward<Fn>(fn));
114 }
else if constexpr (
requires { graph.for_each_neighbor(u, std::forward<Fn>(fn)); }) {
115 graph.for_each_neighbor(u, std::forward<Fn>(fn));
117 for (
const auto& neighbor : graph.neighbors(u)) {
123template <ReadableGraph Graph,
class Fn>
125 if constexpr (
requires { graph.for_each_in_neighbor(v, std::forward<Fn>(fn)); }) {
126 graph.for_each_in_neighbor(v, std::forward<Fn>(fn));
127 }
else if constexpr (
requires { vx_for_each_in_neighbor(graph, v, std::forward<Fn>(fn)); }) {
128 vx_for_each_in_neighbor(graph, v, std::forward<Fn>(fn));
129 }
else if constexpr (
requires { graph.in_neighbors(v); }) {
130 for (
const auto& neighbor : graph.in_neighbors(v)) {
142template <ReadableGraph Graph>
144 if constexpr (
requires { graph.degree(u); }) {
145 return static_cast<std::size_t
>(graph.degree(u));
146 }
else if constexpr (
requires { vx_neighbor_count(graph, u); }) {
147 return static_cast<std::size_t
>(vx_neighbor_count(graph, u));
149 std::size_t count = 0;
155template <ReadableGraph Graph>
157 if constexpr (
requires { graph.has_edge(u, v); }) {
158 return graph.has_edge(u, v);
159 }
else if constexpr (
requires { vx_has_edge(graph, u, v); }) {
160 return vx_has_edge(graph, u, v);
168template <ReadableGraph Graph>
170 if constexpr (
requires { vx_edge_weight(graph, u, v); }) {
171 return vx_edge_weight(graph, u, v);
173 return graph.weight(u, v);
177template <
class Graph,
class Batch>
179 if constexpr (
requires { graph.apply(batch); }) {
182 vx_apply_updates(graph, batch);
constexpr auto neighbor_weight(const T &value) noexcept
constexpr VertexId neighbor_target(const T &value) noexcept
void apply_updates(Graph &graph, const Batch &batch)
void for_each_neighbor(const Graph &graph, VertexId u, Fn &&fn)
auto edge_weight(const Graph &graph, VertexId u, VertexId v)
bool has_edge(const Graph &graph, VertexId u, VertexId v)
constexpr bool is_directed(const Graph &graph)
void for_each_weighted_neighbor(const Graph &graph, VertexId u, Fn &&fn)
constexpr std::uint64_t graph_version(const Graph &graph)
std::size_t neighbor_count(const Graph &graph, VertexId u)
constexpr std::size_t vertex_count(const Graph &graph)
void for_each_in_neighbor(const Graph &graph, VertexId v, Fn &&fn)