}
public:
+ void delist(Child *child)
+ {
+ assert(child->parent() == _parent);
+ assert(!empty());
+
+ if (child == _head)
+ {
+ _head = child->next();
+ }
+
+ if (child == _tail)
+ {
+ _tail = child->prev();
+ }
+
+ // Update parent-child relation
+ _link->unset(child);
+ }
+
+ public:
void prepend(Child *child)
{
if (empty())
assert(parent() == prev->parent());
};
+ public:
+ void detach(void)
+ {
+ // REQUIRE Child SHOULD inherit Node class
+ auto curr = reinterpret_cast<Child *>(this);
+
+ // Update parent-child relation
+ assert(parent() != nullptr);
+ assert(head() != nullptr);
+ head()->delist(curr);
+ assert(parent() == nullptr);
+
+ // Update the link of sibling nodes
+ if (auto prev = curr->prev())
+ {
+ prev->_next = curr->next();
+ }
+
+ if (auto next = curr->next())
+ {
+ next->_prev = curr->prev();
+ }
+
+ // Update the link of the current node
+ _prev = nullptr;
+ _next = nullptr;
+ }
+
private:
const PtrLink<Child, Parent> * const _link;
delete parent;
delete link;
}
+
+TEST(ADT_DLINKED_LINK, detach)
+{
+ auto link = new coco::PtrLink<::Child, ::Parent>{};
+ auto parent = new ::Parent{link};
+
+ auto child_1 = new ::Child{link};
+ auto child_2 = new ::Child{link};
+
+ parent->children()->append(child_1);
+ parent->children()->append(child_2);
+
+ child_1->detach();
+
+ ASSERT_EQ(child_1->parent(), nullptr);
+ ASSERT_EQ(child_1->prev(), nullptr);
+ ASSERT_EQ(child_1->next(), nullptr);
+
+ ASSERT_EQ(child_2->parent(), parent);
+ ASSERT_EQ(child_2->prev(), nullptr);
+
+ ASSERT_EQ(parent->children()->head(), child_2);
+ ASSERT_EQ(parent->children()->tail(), child_2);
+
+ child_2->detach();
+
+ ASSERT_EQ(child_2->parent(), nullptr);
+ ASSERT_EQ(child_2->prev(), nullptr);
+ ASSERT_EQ(child_2->next(), nullptr);
+
+ ASSERT_TRUE(parent->children()->empty());
+ ASSERT_EQ(parent->children()->head(), nullptr);
+ ASSERT_EQ(parent->children()->tail(), nullptr);
+
+ delete child_2;
+ delete child_1;
+ delete parent;
+ delete link;
+}