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- // TODO:
6- // - impl::add_edge should accept: id, first, second
7- // - impl::add_edges_from should accept: edge_ids view, source_id, target_id_range
8- // - impl::remove_edge should accept: id, first, second
9- // - add a get_vertex_properties(id) function
10- // - add a get_edge_properties(id) function
11- // - add at(vertex(_id))
12-
135#pragma once
146
157#include " constants.hpp"
@@ -105,10 +97,10 @@ class graph final {
10597
10698 [[nodiscard]] gl_attr_force_inline vertex_type get_vertex (const types::id_type vertex_id) const {
10799 this ->_verify_vertex_id (vertex_id);
108- if constexpr (type_traits::c_empty_properties<vertex_properties_type>)
109- return vertex_descriptor{vertex_id};
110- else
100+ if constexpr (type_traits::c_non_empty_properties<vertex_properties_type>)
111101 return vertex_descriptor{vertex_id, *this ->_vertex_properties [vertex_id]};
102+ else
103+ return vertex_descriptor{vertex_id};
112104 }
113105
114106 // clang-format on
@@ -125,12 +117,13 @@ class graph final {
125117 this ->_impl .add_vertex ();
126118 const auto new_vertex_id = this ->_n_vertices ++;
127119
128- if constexpr (type_traits::c_empty_properties<vertex_properties_type>)
129- return vertex_descriptor{new_vertex_id};
130- else {
120+ if constexpr (type_traits::c_non_empty_properties<vertex_properties_type>) {
131121 this ->_vertex_properties .push_back (std::make_unique<vertex_properties_type>());
132122 return vertex_descriptor{new_vertex_id, *this ->_vertex_properties .back ()};
133123 }
124+ else {
125+ return vertex_descriptor{new_vertex_id};
126+ }
134127 }
135128
136129 vertex_type add_vertex (vertex_properties_type properties)
@@ -249,32 +242,22 @@ class graph final {
249242 return this ->_impl .degree_map ();
250243 }
251244
252- [[nodiscard]] gl_attr_force_inline auto vertex_properties_map () const noexcept
253- requires(type_traits::c_non_empty_properties<vertex_properties_type>)
254- {
255- return util::deref_view (this ->_vertex_properties );
256- }
257-
258245 // --- edge methods ---
259246
260- // clang-format off
261- // gl_attr_force_inline misplacement
262-
263- const edge_type add_edge (
264- const types::id_type first_id, const types::id_type second_id
265- ) {
247+ const edge_type add_edge (const types::id_type first_id, const types::id_type second_id) {
266248 this ->_verify_vertex_id (first_id);
267249 this ->_verify_vertex_id (second_id);
268250
269251 const auto new_edge_id = this ->_n_unique_edges ++;
270252 this ->_impl .add_edge (new_edge_id, first_id, second_id);
271253
272- if constexpr (type_traits::c_empty_properties<edge_properties_type>) {
273- return edge_type{new_edge_id, first_id, second_id};
254+ if constexpr (type_traits::c_non_empty_properties<edge_properties_type>) {
255+ const auto & p =
256+ this ->_edge_properties .emplace_back (std::make_unique<edge_properties_type>());
257+ return edge_type{new_edge_id, first_id, second_id, *p};
274258 }
275259 else {
276- const auto & p = this ->_edge_properties .emplace_back (std::make_unique<edge_properties_type>());
277- return edge_type{new_edge_id, first_id, second_id, *p};
260+ return edge_type{new_edge_id, first_id, second_id};
278261 }
279262 }
280263
@@ -291,25 +274,29 @@ class graph final {
291274 const auto new_edge_id = this ->_n_unique_edges ++;
292275 this ->_impl .add_edge (new_edge_id, first_id, second_id);
293276
294- auto & p = this ->_edge_properties .emplace_back (std::make_unique<edge_properties_type>(properties));
277+ auto & p =
278+ this ->_edge_properties .emplace_back (std::make_unique<edge_properties_type>(properties));
295279 return edge_type{new_edge_id, first_id, second_id, *p};
296280 }
297281
298- // clang-format on
282+ // clang-format off
283+ // gl_attr_force_inline misplacement
299284
300- const gl_attr_force_inline edge_type
285+ gl_attr_force_inline const edge_type
301286 add_edge (const vertex_type& first, const vertex_type& second) {
302287 return this ->add_edge (first.id (), second.id ());
303288 }
304289
305- const gl_attr_force_inline edge_type add_edge (
290+ gl_attr_force_inline const edge_type add_edge (
306291 const vertex_type& first, const vertex_type& second, const edge_properties_type& properties
307292 )
308293 requires(type_traits::c_non_empty_properties<edge_properties_type>)
309294 {
310295 return this ->add_edge (first.id (), second.id (), properties);
311296 }
312297
298+ // clang-format on
299+
313300 void add_edges_from (
314301 const types::id_type source_id,
315302 const type_traits::c_sized_range_of<types::id_type> auto & target_id_range
@@ -376,10 +363,10 @@ class graph final {
376363 this ->_verify_vertex_id (first_id);
377364 this ->_verify_vertex_id (second_id);
378365
379- if constexpr (type_traits::c_empty_properties<edge_properties_type>)
380- return this ->_impl .get_edge (first_id, second_id);
381- else
366+ if constexpr (type_traits::c_non_empty_properties<edge_properties_type>)
382367 return this ->_impl .get_edge (first_id, second_id, this ->_edge_properties );
368+ else
369+ return this ->_impl .get_edge (first_id, second_id);
383370 }
384371
385372 [[nodiscard]] gl_attr_force_inline std::optional<edge_type> get_edge (
@@ -394,10 +381,10 @@ class graph final {
394381 this ->_verify_vertex_id (first_id);
395382 this ->_verify_vertex_id (second_id);
396383
397- if constexpr (type_traits::c_empty_properties<edge_properties_type>)
398- return this ->_impl .get_edges (first_id, second_id);
399- else
384+ if constexpr (type_traits::c_non_empty_properties<edge_properties_type>)
400385 return this ->_impl .get_edges (first_id, second_id, this ->_edge_properties );
386+ else
387+ return this ->_impl .get_edges (first_id, second_id);
401388 }
402389
403390 [[nodiscard]] gl_attr_force_inline std::vector<edge_type> get_edges (
@@ -427,16 +414,28 @@ class graph final {
427414
428415 [[nodiscard]] inline auto adjacent_edges (const types::id_type vertex_id) const {
429416 this ->_verify_vertex_id (vertex_id);
430- if constexpr (type_traits::c_empty_properties<edge_properties_type>)
431- return this ->_impl .adjacent_edges (vertex_id);
432- else
417+ if constexpr (type_traits::c_non_empty_properties<edge_properties_type>)
433418 return this ->_impl .adjacent_edges (vertex_id, this ->_edge_properties );
419+ else
420+ return this ->_impl .adjacent_edges (vertex_id);
434421 }
435422
436423 [[nodiscard]] gl_attr_force_inline auto adjacent_edges (const vertex_type& vertex) const {
437424 return this ->adjacent_edges (vertex.id ());
438425 }
439426
427+ [[nodiscard]] inline auto at (const types::id_type vertex_id) const {
428+ this ->_verify_vertex_id (vertex_id);
429+ if constexpr (type_traits::c_non_empty_properties<edge_properties_type>)
430+ return this ->_impl .at (vertex_id, this ->_edge_properties );
431+ else
432+ return this ->_impl .at (vertex_id);
433+ }
434+
435+ [[nodiscard]] gl_attr_force_inline auto at (const vertex_type& vertex) const {
436+ return this ->at (vertex.id ());
437+ }
438+
440439 // --- incidence methods ---
441440
442441 [[nodiscard]] bool are_incident (const types::id_type first_id, const types::id_type second_id)
@@ -477,6 +476,40 @@ class graph final {
477476 return edge_1.is_incident_with (edge_2.first ()) or edge_1.is_incident_with (edge_2.second ());
478477 }
479478
479+ // --- property methods ---
480+
481+ [[nodiscard]] gl_attr_force_inline auto vertex_properties_map () const noexcept
482+ requires(type_traits::c_non_empty_properties<vertex_properties_type>)
483+ {
484+ return util::deref_view (this ->_vertex_properties );
485+ }
486+
487+ [[nodiscard]] gl_attr_force_inline vertex_properties_type& get_vertex_properties (
488+ const types::id_type id
489+ ) const
490+ requires(type_traits::c_non_empty_properties<vertex_properties_type>)
491+ {
492+ this ->_verify_vertex_id (id);
493+ return *this ->_vertex_properties [id];
494+ }
495+
496+ [[nodiscard]] gl_attr_force_inline auto edge_properties_map () const noexcept
497+ requires(type_traits::c_non_empty_properties<edge_properties_type>)
498+ {
499+ return util::deref_view (this ->_edge_properties );
500+ }
501+
502+ [[nodiscard]] gl_attr_force_inline edge_properties_type& get_edge_properties (
503+ const types::id_type id
504+ ) const
505+ requires(type_traits::c_non_empty_properties<edge_properties_type>)
506+ {
507+ this ->_verify_vertex_edge (id);
508+ return *this ->_edge_properties [id];
509+ }
510+
511+ // --- stream operators ---
512+
480513 friend std::ostream& operator <<(std::ostream& os, const graph& g) {
481514 if (io::is_option_set (os, io::graph_option::gsf)) {
482515 g._gsf_write (os);
@@ -509,12 +542,13 @@ class graph final {
509542 }
510543
511544 void _verify_edge (const edge_type& edge) const {
512- if (not this ->has_edge (edge))
545+ if (edge.id () >= this ->_n_unique_edges or not this ->has_vertex (edge.first ())
546+ or not this ->has_vertex (edge.second ()))
513547 throw std::invalid_argument (std::format (
514- " Got invalid edge [vertices = ({}, {}) | addr = {}]" ,
548+ " Got invalid edge [id = {}, vertices = ({}, {})]" ,
549+ edge.id (),
515550 edge.first (),
516- edge.second (),
517- io::format (&edge)
551+ edge.second ()
518552 ));
519553 }
520554
0 commit comments