Skip to content

Commit fd89aa4

Browse files
committed
edge properties storage refactor
1 parent 40eeda1 commit fd89aa4

7 files changed

Lines changed: 60 additions & 72 deletions

File tree

include/gl/graph.hpp

Lines changed: 30 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ class graph final {
9393
using edge_properties_map_type = std::conditional_t<
9494
traits::c_empty_properties<edge_properties_type>,
9595
empty_properties_map,
96-
std::vector<std::unique_ptr<edge_properties_type>>>;
96+
std::vector<edge_properties_type>>;
9797

9898
graph& operator=(const graph&) = delete;
9999

@@ -355,18 +355,16 @@ class graph final {
355355
const auto new_edge_id = static_cast<id_type>(this->_n_edges++);
356356
this->_impl.add_edge(new_edge_id, source_id, target_id);
357357

358-
if constexpr (traits::c_non_empty_properties<edge_properties_type>) {
359-
const auto& p =
360-
this->_edge_properties.emplace_back(std::make_unique<edge_properties_type>());
361-
return edge_type{new_edge_id, source_id, target_id, *p};
362-
}
363-
else {
358+
if constexpr (traits::c_non_empty_properties<edge_properties_type>)
359+
return edge_type{
360+
new_edge_id, source_id, target_id, this->_edge_properties.emplace_back()
361+
};
362+
else
364363
return edge_type{new_edge_id, source_id, target_id};
365-
}
366364
}
367365

368366
edge_type add_edge_with(
369-
const id_type source_id, const id_type target_id, const edge_properties_type& properties
367+
const id_type source_id, const id_type target_id, edge_properties_type properties
370368
)
371369
requires(traits::c_non_empty_properties<edge_properties_type>)
372370
{
@@ -376,9 +374,12 @@ class graph final {
376374
const auto new_edge_id = static_cast<id_type>(this->_n_edges++);
377375
this->_impl.add_edge(new_edge_id, source_id, target_id);
378376

379-
auto& p =
380-
this->_edge_properties.emplace_back(std::make_unique<edge_properties_type>(properties));
381-
return edge_type{new_edge_id, source_id, target_id, *p};
377+
return edge_type{
378+
new_edge_id,
379+
source_id,
380+
target_id,
381+
this->_edge_properties.emplace_back(std::move(properties))
382+
};
382383
}
383384

384385
// clang-format off
@@ -402,12 +403,8 @@ class graph final {
402403
const id_type source_id, const traits::c_sized_range_of<id_type> auto& target_id_rng
403404
) {
404405
this->_verify_vertex_id(source_id);
405-
406-
for (auto target_id : target_id_rng) {
406+
for (auto target_id : target_id_rng)
407407
this->_verify_vertex_id(target_id);
408-
if constexpr (traits::c_non_empty_properties<edge_properties_type>)
409-
this->_edge_properties.emplace_back(std::make_unique<edge_properties_type>());
410-
}
411408

412409
const auto prev_n_edges = this->_n_edges;
413410
this->_n_edges += std::ranges::size(target_id_rng);
@@ -416,18 +413,17 @@ class graph final {
416413
source_id,
417414
target_id_rng
418415
);
416+
417+
if constexpr (traits::c_non_empty_properties<edge_properties_type>)
418+
this->_edge_properties.resize(this->_n_edges);
419419
}
420420

421421
void add_edges_from(
422422
vertex_type source, const traits::c_sized_range_of<vertex_type> auto& target_rng
423423
) {
424424
this->_verify_vertex_id(source.id());
425-
426-
for (auto target : target_rng) {
425+
for (auto target : target_rng)
427426
this->_verify_vertex_id(target.id());
428-
if constexpr (traits::c_non_empty_properties<edge_properties_type>)
429-
this->_edge_properties.emplace_back(std::make_unique<edge_properties_type>());
430-
}
431427

432428
const auto prev_n_edges = this->_n_edges;
433429
this->_n_edges += std::ranges::size(target_rng);
@@ -436,6 +432,10 @@ class graph final {
436432
source.id(),
437433
target_rng | std::views::transform(&vertex_type::id)
438434
);
435+
436+
437+
if constexpr (traits::c_non_empty_properties<edge_properties_type>)
438+
this->_edge_properties.resize(this->_n_edges);
439439
}
440440

441441
void remove_edge(const edge_type& edge) {
@@ -554,13 +554,13 @@ class graph final {
554554
if (id >= this->_n_edges)
555555
throw std::out_of_range(std::format("Got invalid edge id [{}]", id));
556556

557-
return *this->_edge_properties[id];
557+
return this->_edge_properties[id];
558558
}
559559

560560
[[nodiscard]] gl_attr_force_inline auto edge_properties_map() const noexcept
561561
requires(traits::c_non_empty_properties<edge_properties_type>)
562562
{
563-
return util::deref_view(this->_edge_properties);
563+
return std::views::all(this->_edge_properties);
564564
}
565565

566566
// --- adjacency and incidence methods ---
@@ -602,10 +602,6 @@ class graph final {
602602
// --- comparison ---
603603

604604
[[nodiscard]] friend bool operator==(const graph& lhs, const graph& rhs) noexcept {
605-
constexpr auto val_eq = [](const auto& ptr_a, const auto& ptr_b) {
606-
return *ptr_a == *ptr_b;
607-
};
608-
609605
if (lhs._n_vertices != rhs._n_vertices or lhs._n_edges != rhs._n_edges)
610606
return false;
611607

@@ -614,7 +610,7 @@ class graph final {
614610
return false;
615611

616612
if constexpr (traits::c_non_empty_properties<edge_properties_type>)
617-
if (not std::ranges::equal(lhs._edge_properties, rhs._edge_properties, val_eq))
613+
if (lhs._edge_properties != rhs._edge_properties)
618614
return false;
619615

620616
return lhs._impl == rhs._impl;
@@ -656,14 +652,8 @@ class graph final {
656652
: _n_vertices{other._n_vertices},
657653
_n_edges{other._n_edges},
658654
_impl{other._impl},
659-
_vertex_properties{other._vertex_properties} {
660-
// Deep copy edge properties
661-
if constexpr (traits::c_non_empty_properties<edge_properties_type>) {
662-
this->_edge_properties.reserve(other._edge_properties.size());
663-
for (const auto& property : other._edge_properties)
664-
this->_edge_properties.push_back(std::make_unique<edge_properties_type>(*property));
665-
}
666-
}
655+
_vertex_properties{other._vertex_properties},
656+
_edge_properties{other._edge_properties} {}
667657

668658
// --- element validation ---
669659

@@ -892,7 +882,9 @@ class graph final {
892882

893883
/// @todo Replace mutability with proper const-correct getter overloads to ensure thread safety guarantees associated with the const qualifier
894884
[[no_unique_address]] mutable vertex_properties_map_type _vertex_properties{};
895-
[[no_unique_address]] edge_properties_map_type _edge_properties{};
885+
886+
/// @todo Replace mutability with proper const-correct getter overloads to ensure thread safety guarantees associated with the const qualifier
887+
[[no_unique_address]] mutable edge_properties_map_type _edge_properties{};
896888
};
897889

898890
// --- general graph utility ---

include/gl/impl/adjacency_list.hpp

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ class adjacency_list final {
163163
}
164164

165165
[[nodiscard]] std::optional<edge_type> edge(
166-
id_type source_id, id_type target_id, const auto& edge_properties_map
166+
id_type source_id, id_type target_id, auto& edge_properties_map
167167
) const
168168
requires(traits::c_has_non_empty_properties<edge_type>)
169169
{
@@ -173,7 +173,7 @@ class adjacency_list final {
173173
if (item_it == out_edges.cend())
174174
return std::nullopt;
175175
return std::make_optional<edge_type>(
176-
item_it->edge_id, source_id, target_id, *edge_properties_map[to_idx(item_it->edge_id)]
176+
item_it->edge_id, source_id, target_id, edge_properties_map[to_idx(item_it->edge_id)]
177177
);
178178
}
179179

@@ -189,15 +189,15 @@ class adjacency_list final {
189189
}
190190

191191
[[nodiscard]] std::vector<edge_type> edges(
192-
id_type source_id, id_type target_id, const auto& edge_properties_map
192+
id_type source_id, id_type target_id, auto& edge_properties_map
193193
) const
194194
requires(traits::c_has_non_empty_properties<edge_type>)
195195
{
196196
return this->_list[source_id]
197197
| std::views::filter([&target_id](auto item) { return item.vertex_id == target_id; })
198198
| std::views::transform([source_id, &edge_properties_map](auto item) {
199199
return edge_type{
200-
item.edge_id, source_id, item.vertex_id, *edge_properties_map[item.edge_id]
200+
item.edge_id, source_id, item.vertex_id, edge_properties_map[item.edge_id]
201201
};
202202
})
203203
| std::ranges::to<std::vector>();
@@ -210,7 +210,7 @@ class adjacency_list final {
210210
}
211211

212212
[[nodiscard]] gl_attr_force_inline auto incident_edges(
213-
id_type vertex_id, const auto& edge_properties_map
213+
id_type vertex_id, auto& edge_properties_map
214214
) const
215215
requires(traits::c_has_non_empty_properties<edge_type>)
216216
{
@@ -226,9 +226,8 @@ class adjacency_list final {
226226
});
227227
}
228228

229-
[[nodiscard]] gl_attr_force_inline auto in_edges(
230-
id_type vertex_id, const auto& edge_properties_map
231-
) const
229+
[[nodiscard]] gl_attr_force_inline auto in_edges(id_type vertex_id, auto& edge_properties_map)
230+
const
232231
requires(traits::c_has_non_empty_properties<edge_type>)
233232
{
234233
return specialized_impl::in_edges(*this, vertex_id)
@@ -237,7 +236,7 @@ class adjacency_list final {
237236
item.edge_id,
238237
item.vertex_id,
239238
vertex_id,
240-
*edge_properties_map[to_idx(item.edge_id)]
239+
edge_properties_map[to_idx(item.edge_id)]
241240
};
242241
});
243242
}
@@ -250,9 +249,8 @@ class adjacency_list final {
250249
});
251250
}
252251

253-
[[nodiscard]] gl_attr_force_inline auto out_edges(
254-
id_type vertex_id, const auto& edge_properties_map
255-
) const
252+
[[nodiscard]] gl_attr_force_inline auto out_edges(id_type vertex_id, auto& edge_properties_map)
253+
const
256254
requires(traits::c_has_non_empty_properties<edge_type>)
257255
{
258256
return this->_list[to_idx(vertex_id)]
@@ -261,7 +259,7 @@ class adjacency_list final {
261259
item.edge_id,
262260
vertex_id,
263261
item.vertex_id,
264-
*edge_properties_map[to_idx(item.edge_id)]
262+
edge_properties_map[to_idx(item.edge_id)]
265263
};
266264
});
267265
}

include/gl/impl/adjacency_matrix.hpp

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -161,15 +161,15 @@ class adjacency_matrix final {
161161
}
162162

163163
[[nodiscard]] std::optional<edge_type> edge(
164-
id_type source_id, id_type target_id, const auto& edge_properties_map
164+
id_type source_id, id_type target_id, auto& edge_properties_map
165165
) const
166166
requires(traits::c_has_non_empty_properties<edge_type>)
167167
{
168168
const auto edge_id = specialized_impl::get_entry(*this, source_id, target_id);
169169
if (edge_id == invalid_id)
170170
return std::nullopt;
171171
return std::make_optional<edge_type>(
172-
edge_id, source_id, target_id, *edge_properties_map[to_idx(edge_id)]
172+
edge_id, source_id, target_id, edge_properties_map[to_idx(edge_id)]
173173
);
174174
}
175175

@@ -185,15 +185,15 @@ class adjacency_matrix final {
185185
}
186186

187187
[[nodiscard]] std::vector<edge_type> edges(
188-
id_type source_id, id_type target_id, const auto& edge_properties_map
188+
id_type source_id, id_type target_id, auto& edge_properties_map
189189
) const
190190
requires(traits::c_has_non_empty_properties<edge_type>)
191191
{
192192
const auto edge_id = specialized_impl::get_entry(*this, source_id, target_id);
193193
if (edge_id == invalid_id)
194194
return std::vector<edge_type>();
195195
return std::vector<edge_type>{
196-
edge_type{edge_id, source_id, target_id, *edge_properties_map[to_idx(edge_id)]}
196+
edge_type{edge_id, source_id, target_id, edge_properties_map[to_idx(edge_id)]}
197197
};
198198
}
199199

@@ -204,7 +204,7 @@ class adjacency_matrix final {
204204
}
205205

206206
[[nodiscard]] gl_attr_force_inline auto incident_edges(
207-
id_type vertex_id, const auto& edge_properties_map
207+
id_type vertex_id, auto& edge_properties_map
208208
) const
209209
requires(traits::c_has_non_empty_properties<edge_type>)
210210
{
@@ -227,9 +227,8 @@ class adjacency_matrix final {
227227
});
228228
}
229229

230-
[[nodiscard]] gl_attr_force_inline auto in_edges(
231-
id_type vertex_id, const auto& edge_properties_map
232-
) const
230+
[[nodiscard]] gl_attr_force_inline auto in_edges(id_type vertex_id, auto& edge_properties_map)
231+
const
233232
requires(traits::c_has_non_empty_properties<edge_type>)
234233
{
235234
return std::views::iota(initial_id_v<id_type>, this->_matrix.size())
@@ -239,7 +238,7 @@ class adjacency_matrix final {
239238
| std::views::transform([this, vertex_id, &edge_properties_map](auto source_id) {
240239
const auto edge_id = specialized_impl::get_entry(*this, source_id, vertex_id);
241240
return edge_type{
242-
edge_id, source_id, vertex_id, *edge_properties_map[to_idx(edge_id)]
241+
edge_id, source_id, vertex_id, edge_properties_map[to_idx(edge_id)]
243242
};
244243
});
245244
}
@@ -258,9 +257,8 @@ class adjacency_matrix final {
258257
});
259258
}
260259

261-
[[nodiscard]] gl_attr_force_inline auto out_edges(
262-
id_type vertex_id, const auto& edge_properties_map
263-
) const
260+
[[nodiscard]] gl_attr_force_inline auto out_edges(id_type vertex_id, auto& edge_properties_map)
261+
const
264262
requires(traits::c_has_non_empty_properties<edge_type>)
265263
{
266264
return this->_matrix[to_idx(vertex_id)] | std::views::enumerate
@@ -274,7 +272,7 @@ class adjacency_matrix final {
274272
edge_id,
275273
vertex_id,
276274
static_cast<id_type>(target_id),
277-
*edge_properties_map[to_idx(edge_id)]
275+
edge_properties_map[to_idx(edge_id)]
278276
};
279277
});
280278
}

include/gl/impl/specialized/adjacency_list.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ struct directed_adjacency_list {
198198
}
199199

200200
[[nodiscard]] gl_attr_force_inline static auto incident_edges(
201-
const impl_type& self, id_type vertex_id, const auto& edge_properties_map
201+
const impl_type& self, id_type vertex_id, auto& edge_properties_map
202202
) {
203203
return util::concat(
204204
self.in_edges(vertex_id, edge_properties_map),
@@ -358,7 +358,7 @@ struct undirected_adjacency_list {
358358
}
359359

360360
[[nodiscard]] gl_attr_force_inline static auto incident_edges(
361-
const impl_type& self, id_type vertex_id, const auto& edge_properties_map
361+
const impl_type& self, id_type vertex_id, auto& edge_properties_map
362362
) {
363363
return self.out_edges(vertex_id, edge_properties_map);
364364
}

include/gl/impl/specialized/adjacency_matrix.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ struct directed_adjacency_matrix {
240240
}
241241

242242
[[nodiscard]] gl_attr_force_inline static auto incident_edges(
243-
const impl_type& self, id_type vertex_id, const auto& edge_properties_map
243+
const impl_type& self, id_type vertex_id, auto& edge_properties_map
244244
) {
245245
return util::concat(
246246
self.in_edges(vertex_id, edge_properties_map),
@@ -434,7 +434,7 @@ struct undirected_adjacency_matrix {
434434
}
435435

436436
[[nodiscard]] gl_attr_force_inline static auto incident_edges(
437-
const impl_type& self, id_type vertex_id, const auto& edge_properties_map
437+
const impl_type& self, id_type vertex_id, auto& edge_properties_map
438438
) {
439439
return self.out_edges(vertex_id, edge_properties_map);
440440
}

include/gl/impl/specialized/flat_adjacency_list.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ struct directed_flat_adjacency_list {
162162
}
163163

164164
[[nodiscard]] gl_attr_force_inline static auto incident_edges(
165-
const impl_type& self, id_type vertex_id, const auto& edge_properties_map
165+
const impl_type& self, id_type vertex_id, auto& edge_properties_map
166166
) {
167167
return util::concat(
168168
self.in_edges(vertex_id, edge_properties_map),
@@ -338,7 +338,7 @@ struct undirected_flat_adjacency_list {
338338
}
339339

340340
[[nodiscard]] gl_attr_force_inline static auto incident_edges(
341-
const impl_type& self, id_type vertex_id, const auto& edge_properties_map
341+
const impl_type& self, id_type vertex_id, auto& edge_properties_map
342342
) {
343343
return self.out_edges(vertex_id, edge_properties_map);
344344
}

0 commit comments

Comments
 (0)