diff --git a/include/graaflib/graph.h b/include/graaflib/graph.h index 7ddd4b7b..b6b6033d 100644 --- a/include/graaflib/graph.h +++ b/include/graaflib/graph.h @@ -179,6 +179,16 @@ class graph { */ [[nodiscard]] vertex_id_t add_vertex(auto&& vertex); + /** + * Add a vertex to the graph with a specific ID + * + * @param vertex The vertex to be added + * @param id The requested ID for the new vertex + * @return vertices_id_t - The ID of the new vertex + * @throws id_taken exception - If the relevant ID is already in use + */ + [[nodiscard]] vertex_id_t add_vertex(auto&& vertex, vertex_id_t id); + /** * Remove a vertex from the graph and update all its neighbors * diff --git a/include/graaflib/graph.tpp b/include/graaflib/graph.tpp index e8e75f79..b503a34d 100644 --- a/include/graaflib/graph.tpp +++ b/include/graaflib/graph.tpp @@ -135,6 +135,18 @@ vertex_id_t graph::add_vertex(auto&& vertex) { return vertex_id; } +template +vertex_id_t graph::add_vertex(auto&& vertex, + vertex_id_t id) { + if (has_vertex(id)) { + throw std::invalid_argument{"Vertex already exists at ID [" + + std::to_string(id) + "]"}; + } + + vertices_.emplace(id, std::forward(vertex)); + return id; +} + template void graph::remove_vertex( vertex_id_t vertex_id) { diff --git a/test/graaflib/graph_test.cpp b/test/graaflib/graph_test.cpp index f6eaf6be..7d60ae6b 100644 --- a/test/graaflib/graph_test.cpp +++ b/test/graaflib/graph_test.cpp @@ -38,6 +38,13 @@ TYPED_TEST(GraphTest, VertexCount) { ASSERT_EQ(graph.vertex_count(), 2); ASSERT_TRUE(graph.has_vertex(vertex_id_2)); ASSERT_EQ(graph.get_vertex(vertex_id_2), 20); + + // WHEN - THEN + constexpr int specific_id = 4; + const auto vertex_specific_id{graph.add_vertex(30, specific_id)}; + ASSERT_EQ(graph.vertex_count(), 3); + ASSERT_TRUE(graph.has_vertex(specific_id)); + ASSERT_EQ(graph.get_vertex(specific_id), 30); } TYPED_TEST(GraphTest, RemoveVertex) { @@ -173,6 +180,24 @@ TYPED_TEST(GraphTest, VertexTests) { EXPECT_FALSE(graph.has_vertex(nonExistingVertexId)); EXPECT_TRUE(graph.has_vertex(vertex_id_2)); EXPECT_EQ(graph.get_vertex(vertex_id_2), 20); + + ASSERT_THROW( + { + try { + // Add vertex to ID that already exists + [[maybe_unused]] const auto duplicate_id{ + graph.add_vertex(50, vertex_id_1)}; + FAIL() + << "Expected std::invalid_argument exception, but no exception " + "was thrown."; + } catch (const std::invalid_argument &ex) { + EXPECT_EQ(ex.what(), fmt::format("Vertex already exists at ID [{}]", + vertex_id_1)); + throw; + } + }, + std::invalid_argument); + EXPECT_EQ(graph.get_vertex(vertex_id_1), 1); } TYPED_TEST(GraphTest, GetEdgeNonExistingEdge) {