I created the following code that some of you have already seen.
It's sort of a multiple value AA array with self tracking.
The problem is, that for some type values, such as delegates, the
comparison is is identical. (basically when the delegate is the
same)
To solve that problem, I'd like to try and turn the Value into
Tuples of the Value and the address of the SingleStore
wrapper(which should be unique).
e.g.,
public Tuple!(TValue, void*)[][TKey] Store;
then I'll simply compare the value and address stored with the
this(inside single store) instead of just this.
Of course, this requires somewhat of a rewrite of the code(trying
it produced all kinds of errors(I tried to fix up all the
references and correlated variables but still a mess, specially
with D's error codes).
It shouldn't be that much trouble though. Essentially where ever
I access the value, I want to instead of use value from the
tuple(a single indirection).
Probably not that easy though?
import std.stdio;
import std.concurrency;
extern (C) int getch();
import std.string;
import std.concurrency;
import core.time;
import core.thread;
import std.container.array;
import std.typecons;
public class SingleStore(TKey, TValue)
{
public TValue Value;
public TKey Key;
public TValue[][TKey] Store;
// Duplicate entries will be removed together as there is no way
to distinguish them
public auto Remove()
{
import std.algorithm;
if (Value == null || Key == null) return;
int count = 0;
for(int i = 0; i < Store[Key].length;i++)
{
auto c = Store[Key][i];
if (c == Value)
{
count++;
Store[Key][i] = null; // Set to null to release any
references if necessary
swap(Store[Key][i], Store[Key][max(0, Store[Key].length -
count)]);
i = i - 1;
}
}
if (count == 1 && Store[Key].length == 1)
{
Store[Key] = null;
Store.remove(Key);
} else
Store[Key] =
Store[Key][0..max(0,Store[Key].length-count)];
Value = null;
Key = null;
}
public static auto New(TKey k, TValue v, ref TValue[][TKey] s)
{
auto o = new SingleStore!(TKey, TValue)(k, v);
o.Store = s;
return o;
}
private this(TKey k, TValue v)
{
Key = k;
Value = v;
}
}
// Creates a static Associative Array that stores multiple values
per key. The object returned by New can then be used to remove
the key/value without having to remember specifically them.
public mixin template ObjectStore(TKey, TValue)
{
// The object store. It is static. Mixin the template into it's
different types to create different types of stores. All objects
of that type are then in the same store.
public static TValue[][TKey] Store;
public static auto New(TKey k, TValue v)
{
(Store[k]) ~= v;
auto o = SingleStore!(TKey, TValue).New(k, v, Store);
return o;
}
public string ToString()
{
return "asdf";
}
}
alias dg = int delegate(int);
//alias dg = string;
class MyStore
{
mixin ObjectStore!(string, dg);
//mixin ObjectStore!(string, string);
}
void main()
{
auto k = "x";
dg d1 = (int x) { return x; };
dg d2 = (int x) { return x; };
dg d3 = d1;
dg d4 = (int x) { return 3*x; };
/*
dg d1 = "a1";
dg d2 = "a2";
dg d3 = "a3";
dg d4 = "a4";
*/
auto s = MyStore.New(k, d1);
writeln(MyStore.Store[k].length);
auto s1 = MyStore.New(k, d2);
writeln(MyStore.Store[k].length);
auto s2 = MyStore.New(k, d3);
writeln(MyStore.Store[k].length);
auto s3 = MyStore.New(k, d4);
writeln(MyStore.Store[k].length);
//auto x = MyStore.Store[k][0](3);
//writeln("-" ~ x);
s1.Remove();
writeln(MyStore.Store[k].length);
s2.Remove();
writeln(MyStore.Store[k].length);
s.Remove();
writeln(MyStore.Store[k].length);
s3.Remove();
getch();
}