I haven't put much thought into this, but here's an idea:
struct MetadataWrapper(T, M) {
immutable T payload; //or const via static if?
M _metadata;
alias payload this;
ref M metadata() { return _metadata;}
}
auto withMetadata(T, Ts...)(Ts args) {
return MetadataWrapper!(T, int)(cast(immutable)(new T(args)),
0);
}
It's short and stupid but works:
void main() {
import std.stdio;
static class MyClass {
this(string s) {
this.s = s;
}
string s;
string stuff() const pure nothrow @safe { return s ~ "
and stuff";}
}
auto foo = withMetadata!MyClass("a string");
writeln("calling stuff on foo: ", foo.stuff());
writeln("foo's metadata is ", foo.metadata);
foo.metadata++;
writeln("foo's metadata is ", foo.metadata);
}
On Sunday, 1 March 2015 at 01:40:40 UTC, Andrei Alexandrescu
wrote:
Tracing garbage collection can afford the luxury of e.g.
mutating data that was immutable during its lifetime.
Reference counting needs to make minute mutations to data while
references to that data are created. In fact, it's not mutation
of the "useful" data, the payload of a data structure; it's
mutation of metadata, additional information about the data
(i.e. a reference count integral).
The RCOs described in DIP74 and also RCSlice discussed in this
forum need to work properly with const and immutable.
Therefore, they need a way to reliably define and access
metadata for a data structure.
One possible solution is to add a "@mutable" or "@metadata"
attribute similar to C++'s keyword "mutable". Walter and I both
dislike that solution because it's hamfisted and leaves too
much opportunity for abuse - people can essentially create
unbounded amounts of mutable payload for an object claimed to
be immutable. That makes it impossible (or unsafe) to optimize
code based on algebraic assumptions.
We have a few candidates for solutions, but wanted to open with
a good discussion first. So, how do you envision a way to
define and access mutable metadata for objects (including
immutable ones)?
Andrei