Skip to content

Instantly share code, notes, and snippets.

@mboedigh
Created December 7, 2023 17:17
Show Gist options
  • Save mboedigh/b93719b96abb3902da0e2c80f8fc750f to your computer and use it in GitHub Desktop.
Save mboedigh/b93719b96abb3902da0e2c80f8fc750f to your computer and use it in GitHub Desktop.
template <typename Map>
concept is_associative = requires(Map& map, Map::key_type& k) {
typename Map::key_type;
typename Map::mapped_type;
typename Map::value_type;
map[k];
};
template <typename Graph>
struct NodeIndexFactory {
constexpr auto operator()() {
if constexpr (is_associative<Graph>) {
using adj_nodes = Graph::mapped_type;
return rng::range_value_t<adj_nodes>();
} else {
using adj_nodes = rng::range_value_t<Graph>;
return rng::range_value_t<adj_nodes>();
}
}
};
template <class Graph>
using node_index_t = decltype(NodeIndexFactory<Graph>()());
template <typename G, typename NodeId = node_index_t<G>>
concept Graph = requires(G& g, NodeId& n) {
// Note: A Graph is a structure to model pairwise relations between objects (nodes) -- wiki
// This Graph concept has the bare minimum functionality for an adjacency graph
// Specifically, graphs only store the pairwise relations for each node and don't require
// maintenance functions (e.g. constructing or maintaining edges)
// A graph is random access range (supports []) with value_type of a range with a value_type that can be
requires rng::range<G>;
requires rng::range<decltype(g[n])>; // g[i] returns a range
{ *g[n].begin() } -> convertible_to<NodeId>; // node_index type can be used as an index into the graph
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment