Skip to content

Commit e67fac3

Browse files
committed
more docs and fixes
1 parent 2a17b98 commit e67fac3

4 files changed

Lines changed: 177 additions & 9 deletions

File tree

docs/style/theme.css

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,25 @@
5858
}
5959

6060
/* Code Blocks */
61-
.md-typeset pre {
61+
.md-typeset .md-code {
6262
border-radius: 0.25rem !important;
63-
overflow: hidden !important;
6463
border: 1px solid var(--md-default-bg-color--lighter);
6564
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
6665
}
6766

67+
/* Let the inner pre tag breathe so tooltips can pop out! */
68+
.md-typeset pre {
69+
overflow: visible !important; /* CRITICAL FIX: Removes the clipping wall */
70+
border: none !important;
71+
box-shadow: none !important;
72+
}
73+
74+
/* Scale down the copy buttons */
75+
.md-typeset .md-code__action {
76+
transform: scale(0.7);
77+
transform-origin: top right;
78+
}
79+
6880
/* Smooth Admonitions */
6981
.md-typeset .admonition, .md-typeset details {
7082
border-radius: 0.5rem;

include/gl/edge_descriptor.hpp

Lines changed: 145 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
// This file is part of the CPP-GL project (https://github.com/SpectraL519/cpp-gl).
33
// Licensed under the MIT License. See the LICENSE file in the project root for full license information.
44

5+
/// @file gl/edge_descriptor.hpp
6+
/// @brief Defines the edge_descriptor class and related aliases, providing a lightweight wrapper for edges in graphs.
7+
58
#pragma once
69

710
#include "gl/attributes/force_inline.hpp"
@@ -16,60 +19,136 @@
1619

1720
namespace gl {
1821

22+
/// @ingroup GL GL-Core
23+
/// @brief A lightweight wrapper representing a graph edge with its endpoints and optional properties.
24+
///
25+
/// **Module:** Part of the @ref GL-Core "Core Graph Components" group.
26+
///
27+
/// The `edge_descriptor` class provides a type-safe and efficient way to represent
28+
/// edges in both directed and undirected graph structures. It encapsulates the unique
29+
/// identifier of the edge, its source and target vertices, and optional property data.
30+
///
31+
/// > [!WARNING] This class is not intended to be instantiated directly.
32+
/// >
33+
/// > Instead, `edge_descriptor` objects should be retrieved from the @ref gl::graph class instance that owns the given edge.
34+
///
35+
/// ### Example Usage
36+
/// ```cpp
37+
/// std::cout << gl::io::verbose << gl::io::with_edge_properties;
38+
/// for (auto v : graph.vertices()) {
39+
/// for (auto e : graph.out_edges(v)) { // (1)!
40+
/// if (e.is_loop()) // (2)!
41+
/// e->weight = 0.0;
42+
/// else
43+
/// e->weight += 1.5; // (3)!
44+
///
45+
/// std::cout << e << "\n"; // (4)!
46+
/// }
47+
/// }
48+
/// ```
49+
///
50+
/// 1\. Retrieve edges using valid `graph` traversal methods like `out_edges()`.
51+
///
52+
/// 2\. Utilize built-in edge utility methods to evaluate the edge type.
53+
///
54+
/// 3\. Access and modify custom property fields via the arrow operator `->`.
55+
///
56+
/// 4\. Print the detailed, formatted edge data using the applied stream manipulators.
57+
/// *Example output:* `[id: 12 | source: 3, target: 7 | weight: 1.5]`
58+
///
59+
/// ### Template Parameters
60+
/// | Parameter | Description | Default | Constraint |
61+
/// | :------------- | :--- | :--- | :--- |
62+
/// | DirectionalTag | Tag specifying if the edge is directed or undirected. | @ref gl::directed_t "directed_t" | [**c_graph_directional_tag**](gl_traits.md#gl-traits-c-graph-directional-tag) |
63+
/// | Properties | The type of property data attached to the edge. | @ref gl::empty_properties "empty_properties" | [**c_properties**](gl_traits.md#gl-traits-c-properties) |
64+
/// | IdType | The underlying integer type used for the IDs. | @ref gl::default_id_type "default_id_type" | [**c_id_type**](gl_traits.md#gl-traits-c-id-type) |
65+
///
66+
/// ### See Also
67+
/// * @ref gl::vertex_descriptor : For the corresponding vertex wrapper class.
68+
/// * @ref gl::graph : For the owning graph class that manages edge descriptors.
1969
template <
2070
traits::c_graph_directional_tag DirectionalTag = directed_t,
2171
traits::c_properties Properties = empty_properties,
2272
traits::c_id_type IdType = default_id_type>
2373
class edge_descriptor final {
2474
public:
75+
/// @brief The fully instantiated type of this edge descriptor.
2576
using type = edge_descriptor<DirectionalTag, Properties, IdType>;
77+
/// @brief The identifier type used for edges and vertices.
2678
using id_type = IdType;
79+
/// @brief The tag denoting whether the edge is directed or undirected.
2780
using directional_tag = DirectionalTag;
81+
/// @brief The type of properties associated with the edge.
2882
using properties_type = Properties;
2983

3084
friend directional_tag;
3185

86+
/// @brief Default constructor, initializes to an invalid edge.
3287
edge_descriptor() {
3388
*this = edge_descriptor::invalid();
3489
}
3590

91+
/// @brief Constructs an edge descriptor with the given IDs (for empty properties).
92+
/// @param id The unique identifier for the edge.
93+
/// @param source The unique identifier for the source vertex.
94+
/// @param target The unique identifier for the target vertex.
3695
explicit edge_descriptor(const id_type id, const id_type source, const id_type target)
3796
requires(traits::c_empty_properties<properties_type>)
3897
: _id(id), _vertices(source, target) {}
3998

99+
/// @brief Constructs an edge descriptor with the given IDs and properties.
100+
/// @param id The unique identifier for the edge.
101+
/// @param source The unique identifier for the source vertex.
102+
/// @param target The unique identifier for the target vertex.
103+
/// @param properties A reference to the property data to associate with this edge.
40104
explicit edge_descriptor(
41105
const id_type id, const id_type source, const id_type target, properties_type& properties
42106
)
43107
requires(traits::c_non_empty_properties<properties_type>)
44108
: _id(id), _vertices(source, target), _properties(properties) {}
45109

110+
/// @brief Returns an invalid edge descriptor (for empty properties).
111+
/// @return An `edge_descriptor` holding `invalid_id` for edge and vertex IDs.
46112
[[nodiscard]] gl_attr_force_inline static edge_descriptor invalid() noexcept
47113
requires(traits::c_empty_properties<properties_type>)
48114
{
49115
return edge_descriptor(invalid_id, invalid_id, invalid_id);
50116
}
51117

118+
/// @brief Returns an invalid edge descriptor (for non-empty properties).
119+
/// @return An `edge_descriptor` holding `invalid_id` endpoints and empty properties.
52120
[[nodiscard]] gl_attr_force_inline static edge_descriptor invalid() noexcept
53121
requires(traits::c_non_empty_properties<properties_type>)
54122
{
55123
static properties_type invalid_properties{};
56124
return edge_descriptor(invalid_id, invalid_id, invalid_id, invalid_properties);
57125
}
58126

127+
/// @brief Copy constructor.
59128
edge_descriptor(const edge_descriptor&) = default;
129+
/// @brief Copy assignment operator.
60130
edge_descriptor& operator=(const edge_descriptor&) = default;
61131

132+
/// @brief Move constructor.
62133
edge_descriptor(edge_descriptor&&) noexcept = default;
134+
/// @brief Move assignment operator.
63135
edge_descriptor& operator=(edge_descriptor&&) noexcept = default;
64136

137+
/// @brief Destructor.
65138
~edge_descriptor() = default;
66139

140+
/// @brief Equality comparison operator for directed edges.
141+
/// @param other The edge descriptor to compare against.
142+
/// @return `true` if IDs and exact endpoint pairs match, `false` otherwise.
67143
[[nodiscard]] bool operator==(const edge_descriptor& other) const noexcept
68144
requires(traits::c_directed_edge<type>)
69145
{
70146
return this->_id == other._id and (this->_vertices == other._vertices);
71147
}
72148

149+
/// @brief Equality comparison operator for undirected edges.
150+
/// @param other The edge descriptor to compare against.
151+
/// @return `true` if IDs and endpoint pairs match (order independent), `false` otherwise.
73152
[[nodiscard]] bool operator==(const edge_descriptor& other) const noexcept
74153
requires(traits::c_undirected_edge<type>)
75154
{
@@ -78,32 +157,46 @@ class edge_descriptor final {
78157
or (this->_vertices == other.incident_vertices_r()));
79158
}
80159

160+
/// @brief Boolean conversion operator.
161+
/// @return `true` if the edge is valid.
81162
[[nodiscard]] gl_attr_force_inline operator bool() const noexcept {
82163
return this->is_valid();
83164
}
84165

166+
/// @brief Checks if the edge represents a directed connection.
167+
/// @return `true` if `DirectionalTag` is `directed_t`.
85168
[[nodiscard]] constexpr bool is_directed() const noexcept {
86169
return traits::c_directed_edge<type>;
87170
}
88171

172+
/// @brief Checks if the edge represents an undirected connection.
173+
/// @return `true` if `DirectionalTag` is `undirected_t`.
89174
[[nodiscard]] constexpr bool is_undirected() const noexcept {
90175
return traits::c_undirected_edge<type>;
91176
}
92177

178+
/// @brief Checks if the edge descriptor is valid.
179+
/// @return `true` if the edge ID and both endpoints are not equal to `invalid_id`.
93180
[[nodiscard]] bool is_valid() const noexcept {
94181
return this->_id != invalid_id and this->_vertices.first != invalid_id
95182
and this->_vertices.second != invalid_id;
96183
}
97184

185+
/// @brief Returns the edge ID.
186+
/// @return The underlying integer ID of the edge.
98187
[[nodiscard]] gl_attr_force_inline id_type id() const noexcept {
99188
return this->_id;
100189
}
101190

191+
/// @brief Retrieves the endpoints of the edge as a pair.
192+
/// @return A `homogeneous_pair` representing `(source, target)`.
102193
[[nodiscard]] gl_attr_force_inline homogeneous_pair<id_type> incident_vertices(
103194
) const noexcept {
104195
return this->_vertices;
105196
}
106197

198+
/// @brief Retrieves the reversed endpoints of the edge as a pair.
199+
/// @return A `homogeneous_pair` representing `(target, source)`.
107200
[[nodiscard]] gl_attr_force_inline homogeneous_pair<id_type> incident_vertices_r(
108201
) const noexcept {
109202
return std::make_pair(this->_vertices.second, this->_vertices.first);
@@ -112,16 +205,24 @@ class edge_descriptor final {
112205
// clang-format off
113206
// gl_attr_force_inline misplacement
114207

208+
/// @brief Returns the source vertex ID.
209+
/// @return The underlying integer ID of the source vertex.
115210
[[nodiscard]] gl_attr_force_inline const id_type source() const noexcept {
116211
return this->_vertices.first;
117212
}
118213

214+
/// @brief Returns the target vertex ID.
215+
/// @return The underlying integer ID of the target vertex.
119216
[[nodiscard]] gl_attr_force_inline const id_type target() const noexcept {
120217
return this->_vertices.second;
121218
}
122219

123220
// clang-format on
124221

222+
/// @brief Gets the other endpoint of the edge given one of its incident vertices.
223+
/// @param vertex_id The ID of one incident vertex.
224+
/// @return The ID of the opposite vertex.
225+
/// @throws std::invalid_argument If the provided `vertex_id` is not incident to this edge.
125226
[[nodiscard]] const id_type other(const id_type vertex_id) const {
126227
if (vertex_id == this->_vertices.first)
127228
return this->_vertices.second;
@@ -132,47 +233,69 @@ class edge_descriptor final {
132233
throw std::invalid_argument(std::format("Got invalid vertex id: {}", vertex_id));
133234
}
134235

236+
/// @brief Checks if a specific vertex is incident to this edge.
237+
/// @param vertex_id The vertex ID to query.
238+
/// @return `true` if the vertex is either the source or the target, `false` otherwise.
135239
[[nodiscard]] gl_attr_force_inline bool is_incident_with(const id_type vertex_id
136240
) const noexcept {
137241
return vertex_id == this->_vertices.first or vertex_id == this->_vertices.second;
138242
}
139243

140-
// true if the given vertex is the `source` of the edge
244+
/// @brief Checks if the given vertex acts as the source for this edge.
245+
/// @param vertex_id The vertex ID to query.
246+
/// @return `true` if the vertex is the source (or any endpoint for undirected graphs).
141247
[[nodiscard]] gl_attr_force_inline bool is_incident_from(const id_type vertex_id
142248
) const noexcept {
143249
return directional_tag::is_incident_from(*this, vertex_id);
144250
}
145251

146-
// true if the given vertex is the `target` vertex of the edge
252+
/// @brief Checks if the given vertex acts as the target for this edge.
253+
/// @param vertex_id The vertex ID to query.
254+
/// @return `true` if the vertex is the target (or any endpoint for undirected graphs).
147255
[[nodiscard]] gl_attr_force_inline bool is_incident_to(const id_type vertex_id) const noexcept {
148256
return directional_tag::is_incident_to(*this, vertex_id);
149257
}
150258

259+
/// @brief Checks if the edge is a self-loop.
260+
/// @return `true` if the source and target are the same vertex, `false` otherwise.
151261
[[nodiscard]] gl_attr_force_inline bool is_loop() const noexcept {
152262
return this->_vertices.first == this->_vertices.second;
153263
}
154264

265+
/// @brief Returns a reference to the edge properties.
266+
/// @return A reference to the associated `properties_type`.
267+
/// @throws std::logic_error If the edge descriptor is invalid.
155268
[[nodiscard]] gl_attr_force_inline properties_type& properties() const
156269
requires(traits::c_non_empty_properties<properties_type>)
157270
{
158271
this->_validate();
159272
return this->_properties.get();
160273
}
161274

275+
/// @brief Arrow operator for accessing properties.
276+
/// @return A pointer to the associated `properties_type`.
277+
/// @throws std::logic_error If the edge descriptor is invalid.
162278
[[nodiscard]] gl_attr_force_inline properties_type* operator->() const
163279
requires(traits::c_non_empty_properties<properties_type>)
164280
{
165281
this->_validate();
166282
return &this->_properties.get();
167283
}
168284

285+
/// @brief Dereference operator for accessing properties.
286+
/// @return A reference to the associated `properties_type`.
287+
/// @throws std::logic_error If the edge descriptor is invalid.
169288
[[nodiscard]] gl_attr_force_inline properties_type& operator*() const
170289
requires(traits::c_non_empty_properties<properties_type>)
171290
{
172291
this->_validate();
173292
return this->_properties.get();
174293
}
175294

295+
/// @brief Output stream operator for edge descriptors.
296+
/// @param os The output stream.
297+
/// @param edge The edge descriptor to write.
298+
/// @return A reference to the output stream.
176299
friend std::ostream& operator<<(std::ostream& os, const edge_descriptor& edge) {
177300
using enum io::detail::option_bit;
178301

@@ -256,11 +379,31 @@ class edge_descriptor final {
256379
std::reference_wrapper<properties_type>> _properties;
257380
};
258381

382+
/// @ingroup GL GL-Core
383+
/// @brief Type alias for a directed edge descriptor.
384+
///
385+
/// Pre-binds the `DirectionalTag` of `edge_descriptor` to `directed_t`.
386+
///
387+
/// ### Template Parameters
388+
/// | Parameter | Description | Default | Constraint |
389+
/// | :--------- | :--- | :--- | :--- |
390+
/// | Properties | The type of property data attached to the edge. | @ref gl::empty_properties "empty_properties" | [**c_properties**](gl_traits.md#gl-traits-c-properties) |
391+
/// | IdType | The underlying integer type used for the IDs. | @ref gl::default_id_type "default_id_type" | [**c_id_type**](gl_traits.md#gl-traits-c-id-type) |
259392
template <
260393
traits::c_properties Properties = empty_properties,
261394
traits::c_id_type IdType = default_id_type>
262395
using directed_edge = edge_descriptor<directed_t, Properties, IdType>;
263396

397+
/// @ingroup GL GL-Core
398+
/// @brief Type alias for an undirected edge descriptor.
399+
///
400+
/// Pre-binds the `DirectionalTag` of `edge_descriptor` to `undirected_t`.
401+
///
402+
/// ### Template Parameters
403+
/// | Parameter | Description | Default | Constraint |
404+
/// | :--------- | :--- | :--- | :--- |
405+
/// | Properties | The type of property data attached to the edge. | @ref gl::empty_properties "empty_properties" | [**c_properties**](gl_traits.md#gl-traits-c-properties) |
406+
/// | IdType | The underlying integer type used for the IDs. | @ref gl::default_id_type "default_id_type" | [**c_id_type**](gl_traits.md#gl-traits-c-id-type) |
264407
template <
265408
traits::c_properties Properties = empty_properties,
266409
traits::c_id_type IdType = default_id_type>

include/gl/vertex_descriptor.hpp

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,24 +36,35 @@ namespace gl {
3636
///
3737
/// ### Example Usage
3838
/// ```cpp
39+
/// std::cout << gl::io::with_vertex_properties; // (1)!
3940
/// for (auto v : graph.vertices()) {
40-
/// std::cout << "Node ID: " << v.id() << " | "; // (1)!
4141
/// if (v->parent == gl::invalid_id) // (2)!
42-
/// std::cout << "ROOT | Level: " << v->level << "\n";
42+
/// v->level = 0;
4343
/// else
44-
/// std::cout << "Parent: " << v->parent << " | Level: " << v->level << "\n";
44+
/// v->level = graph.vertex(v->parent)->level + 1; // (3)!
45+
///
46+
/// std::cout << v << "\n"; // (4)!
4547
/// }
4648
/// ```
4749
///
48-
/// 1\. Access the underlying structural ID
50+
/// 1\. Apply the stream manipulator to ensure custom property data is included in the output.
51+
///
52+
/// 2\. Use the arrow operator `->` to read custom properties attached to the vertex.
4953
///
50-
/// 2\. Use the arrow operator to access/modify custom property fields
54+
/// 3\. Access another vertex via the `graph` using its ID, and modify the current vertex's properties.
55+
///
56+
/// 4\. Idiomatic output formatting.
57+
/// *Example output:* `5[parent: 0, level: 1]`
5158
///
5259
/// ### Template Parameters
5360
/// | Parameter | Description | Default | Constraint |
5461
/// | :--------- | :--- | :--- | :--- |
5562
/// | Properties | The type of property data attached to the vertex. | @ref gl::empty_properties "empty_properties" | [**c_properties**](gl_traits.md#gl-traits-c-properties) |
5663
/// | IdType | The underlying integer type used for the vertex ID. | @ref gl::default_id_type "default_id_type" | [**c_id_type**](gl_traits.md#gl-traits-c-id-type) |
64+
///
65+
/// ### See Also
66+
/// * @ref gl::edge_descriptor : For the corresponding edge wrapper class.
67+
/// * @ref gl::graph : For the owning graph class that manages vertex descriptors.
5768
template <
5869
traits::c_properties Properties = empty_properties,
5970
traits::c_id_type IdType = default_id_type>

0 commit comments

Comments
 (0)