What are best practices around toString?

christian.koestlin christian.koestlin at gmail.com
Fri Sep 30 13:11:56 UTC 2022


Dear Dlang experts,

up until now I was perfectly happy with implementing `(override) 
string toString() const` or something to get nicely formatted 
(mostly debug) output for my structs, classes and exceptions.

But recently I stumbled upon 
https://wiki.dlang.org/Defining_custom_print_format_specifiers 
and additionally 
https://github.com/dlang/dmd/blob/4ff1eec2ce7d990dcd58e5b641ef3d0a1676b9bb/druntime/src/object.d#L2637 which at first sight is great, because it provides the same customization of an objects representation with less memory allocations.

When grepping through phobos, there are a bunch of "different" 
signatures implemented for this, e.g.

```d
...
phobos/std/typecons.d:        void toString(DG)(scope DG sink) 
const
...
phobos/std/typecons.d:        void toString(DG, Char)(scope DG 
sink,  scope const ref FormatSpec!Char fmt) const
...
phobos/std/typecons.d:        void toString()(scope void 
delegate(const(char)[]) sink, scope const ref FormatSpec!char fmt)
...
phobos/std/sumtype.d:        void toString(this This, Sink, 
Char)(ref Sink sink, const ref FormatSpec!Char fmt);
...
```
to just show a few.

Furthermore, when one works with instances of struct, objects or 
exceptions a `aInstance.toString()` does not "work" when one only 
implements the sink interface (which is to be expected), whereas 
a `std.conv.to!string` or a formatted write with `%s` always 
works (no matter what was used to implement the toString).

So I wonder, what is best practice in the community and would it 
make sense to add something to dscanner, that "warns" on usages 
of `aInstance.toString()`?


Kind regards,
Christian



More information about the Digitalmars-d-learn mailing list