Hello all,
I'm writing some code which is meant to represent a network of linked nodes.
Each node is represented by a struct that contains the node's ID and an array of
links to other nodes. Just as an experiment, I've tried out two different ways
of doing this:
////////////////////////////////////////////////////////////////
struct Node1
{
uint id;
Link[] links;
this(uint id)
{
this.id = id;
}
void addLink(uint l)
{
links ~= Link(l);
}
}
struct Node2
{
uint id;
Array!(Link) links;
this(uint id)
{
this.id = id;
}
void addLink(uint l)
{
links.insert(Link(l));
}
}
////////////////////////////////////////////////////////////////
Now, either of these seem to work fine per se. Just as a simple test, you can
do something like,
auto n1 = Node1(1);
auto n2 = Node2(2);
n1.addLink(5);
n1.addLink(6);
writeln(n1.links[0].id, "\t", n1.links[1].id);
n2.addLink(7);
n2.addLink(8);
writeln(n2.links[0].id, "\t", n2.links[1].id);
... and all the correct results come out as you'd expect.
Now, suppose I want to implement a struct that groups together these nodes.
Here's a go:
////////////////////////////////////////////////////////////////
struct Network(Node)
{
Node[uint] nodes;
void add(uint i, uint j)
{
if((i in nodes) is null)
nodes[i] = Node(i);
if((j in nodes) is null)
nodes[j] = Node(j);
nodes[i].addLink(j);
nodes[j].addLink(i);
}
void print()
{
foreach(k; nodes.keys)
{
write("[", k, "]");
foreach(l; nodes[k].links)
write(" ", l.id);
writeln();
}
writeln();
}
}
////////////////////////////////////////////////////////////////
However, while this structure (which is essentially a wrapper around an
associative array between node IDs and actual nodes) works fine with Node1, the
dynamic array-based node structure, it fails with Node2, which is based on
std.container.Array.
e.g. this works:
Network!Node1 net1;
net1.add(1, 5);
net1.print();
net1.add(1, 6);
net1.print();
... but this segfaults:
Network!Node2 net2;
net2.add(1, 7);
I'm a bit confused as to why. By the look of things it's actually the creation
of new entries in the Node[uint] associative array, rather than appending links
to the individual nodes. Can anyone advise?
Full working (or rather, failing:-) code attached for reference.
On a slightly different note, where std.container.Array is concerned: how come I
can't use a foreach(i, x; myArray) formulation? I.e. one where the foreach can
infer the index value as well as the contained value ...
import std.container, std.stdio, std.typecons;
alias Tuple!(uint, "id") Link;
struct Node1
{
uint id;
Link[] links;
this(uint id)
{
this.id = id;
}
void addLink(uint l)
{
links ~= Link(l);
}
}
struct Node2
{
uint id;
Array!(Link) links;
this(uint id)
{
this.id = id;
}
void addLink(uint l)
{
links.insert(Link(l));
}
}
struct Network(Node)
{
Node[uint] nodes;
void add(uint i, uint j)
{
if((i in nodes) is null)
nodes[i] = Node(i);
if((j in nodes) is null)
nodes[j] = Node(j);
nodes[i].addLink(j);
nodes[j].addLink(i);
}
void print()
{
foreach(k; nodes.keys)
{
write("[", k, "]");
foreach(l; nodes[k].links)
write(" ", l.id);
writeln();
}
writeln();
}
}
void main()
{
auto n1 = Node1(1);
auto n2 = Node2(2);
n1.addLink(5);
n1.addLink(6);
writeln(n1.links[0].id, "\t", n1.links[1].id);
n2.addLink(7);
n2.addLink(8);
writeln(n2.links[0].id, "\t", n2.links[1].id);
Network!Node1 net1;
Network!Node2 net2;
net1.add(1, 5);
net1.print();
net1.add(1, 6);
net1.print();
// segfaults on this command
net2.add(1, 7);
}