Skip to content

Commit d591f63

Browse files
committed
almost done - I think
1 parent e81bba4 commit d591f63

2 files changed

Lines changed: 83 additions & 55 deletions

File tree

include/gl/graph.hpp

Lines changed: 81 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,6 @@
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

tests/source/gl/test_graph.cpp

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,6 @@ using add_edge_property = gl::graph_traits<
9090

9191
using vertex_id_list = std::vector<gl::types::id_type>;
9292

93-
// TODO: removef
94-
template <gl::type_traits::c_instantiation_of<gl::vertex_descriptor> VertexType>
95-
using vertex_ref_list = std::vector<gl::types::const_ref_wrap<VertexType>>;
96-
9793
inline constexpr auto get_id = [](auto&& element) -> gl::types::id_type { return element.id(); };
9894

9995
TEST_CASE_TEMPLATE_DEFINE("graph structure tests", TraitsType, graph_traits_template) {
@@ -867,13 +863,10 @@ TEST_CASE_TEMPLATE_INSTANTIATE(
867863
gl::matrix_graph_traits<gl::undirected_t> // undirected adjacency matrix
868864
);
869865

870-
TEST_CASE_TEMPLATE_DEFINE(
871-
"vertex_properties_map() should return a correct map", TraitsType, vp_graph_traits_template
872-
) {
866+
TEST_CASE_TEMPLATE_DEFINE("vertex properties getter tests", TraitsType, vp_graph_traits_template) {
873867
using sut_type = gl::graph<TraitsType>;
874868

875869
sut_type sut{constants::n_elements};
876-
877870
for (auto vertex : sut.vertices())
878871
vertex.properties() = std::format("vertex_{}", vertex.id());
879872

@@ -882,6 +875,7 @@ TEST_CASE_TEMPLATE_DEFINE(
882875
for (auto [id, property] : std::views::zip(sut.vertex_ids(), map)) {
883876
CHECK_EQ(property, std::format("vertex_{}", id));
884877
CHECK_EQ(map[id], std::format("vertex_{}", id));
878+
CHECK_EQ(sut.get_vertex_properties(id), std::format("vertex_{}", id));
885879
}
886880
}
887881

0 commit comments

Comments
 (0)