Shared global initialization
WB
witold.baryluk at gmail.com
Sat Aug 2 21:18:26 UTC 2025
I like global registration patterns, for some stuff. Things like
command line flags in very big projects with many tunable in
various subsystems. Or registering things like benchmarks, etc.
See for example Abseil flags, Go flags, or google benchmark tests.
But I think in D it is hard to pull off compared to for example
C++. (Or some compiler tricks with linker sections).
Lets consider code like this:
```d
// Library code, i.e. flags.d
shared final class Flag {
this(string name, string help = "") {
import std.stdio : writefln;
writefln("Constructing %s", name);
name_ = name;
help_ = help;
}
const string name_;
const string help_;
int val_;
void print() {
import std.stdio : writefln;
writefln("%s=%d # %s", name_, val_, help_);
}
shared static Flag[] flags;
}
string flag(string name, string help = "") {
import std.conv : text;
string s;
s ~= i"shared Flag $(name);\n".text;
// Alternatively we can do append to `Flag.flags` in `Flag`
constructor.
s ~= i"shared static this() { $(name) = new Flag(\"$(name)\",
\"$(help)\"); Flag.flags ~= $(name); }\n".text;
return s;
}
// User code, i.e. main.d
mixin(flag("foo", "--foo bar baz"));
mixin(flag("x", "--x y z"));
void main() {
foo.print();
x.print();
}
```
I really wish I was able to do something like this instead:
```d
shared final class Flag {
this(string name, string help = "") {
import std.stdio : writefln;
writefln("Constructing %s", name);
name_ = name;
help_ = help;
flags ~= this;
}
const string name_;
const string help_;
int val_;
void print() {
import std.stdio : writefln;
writefln("%s=%d # %s", name_, val_, help_);
}
shared static Flag[] flags;
}
shared Flag foo = new Flag("foo", "--foo bar baz");
shared Flag x = new Flag("foo", "--x y z");
void main() {
foo.print();
x.print();
}
```
But that does not work afaik.
And also for this to not be legal: `Flag foo = new Flag("foo",
"--foo bar baz");` (non-shared instantiation as global not
allowed, maybe only in unittests allowed).
Am I missing something?
(Another pattern is to make `Flag` a immutable struct, and
annotate it with UDF, then have at the end some mixin that
iterates over all flags and initializes / registers them, but
that is not pretty either).
```d
@flag("foo")
immutable Flag foo = FlagSpec("--foo bar baz");
mixin(iter_flags_and_register());
```
or something similar.
There must be some better, easier and less error prone way of
doing this.
Cheers.
More information about the Digitalmars-d
mailing list