Please note a variation of the classic singly-linked-list structure below:
#include <stdio.h>
struct Node;
struct SList {
Node* root = nullptr;
};
struct Node {
int* data = nullptr;
SList* parent = nullptr;
Node* next = nullptr;
Node(Node const&) = delete;
Node& operator=(Node const&) = delete;
constexpr Node(int data, SList& list)
: data(new int(data)), parent(&list), next(list.root) {
list.root = this;
}
constexpr ~Node() {
Node** p = &parent->root;
while (*p != this) {
p = &((*p)->next);
}
(*p) = this->next;
delete data;
}
};
constexpr int test() {
SList list;
Node n1(10, list);
Node n2(20, list);
Node n3(30, list);
{ Node n3_5(35, list); }
auto pn4 = new Node(40, list);
Node n5 = Node(50, list);
delete pn4;
int sum = 0;
for (auto p = list.root; p; p = p->next) {
sum += *p->data;
}
return sum;
}
int main() {
auto constexpr retval = test();
return retval;
}
There is a very subtle bug in there. If any of the references are const (like Node const n2(20, list);
), we're storing a non-const pointer to a const object in the constructor of Node
. This pointer is then used in the destructor of other other Node
objects and cause undefined behavior. Making Node* next
mutable is not an option because you can't use mutable fields in a constexpr function.
This structure is inherently not const-friendly. I either want to fix this code somehow, so it doesn't silently cause UB for all const instances, or disable creating const objects of type Node
entirely (as a compile-time error). Since objects are not const in their constructor, I am not sure how one would do either of those.