On Sunday, 7 January 2024 at 09:49:36 UTC, Renato wrote:
Hi, I wanted to customize the toString implementation for my structs.

So I wrote a mixin for doing that:

Alternative format similar to what you already have:
```d
import std.format;

mixin template ToStringMixin() {
        void toString(W)(ref W writer) {
                alias T = typeof(this);
writer.formattedWrite("%s(\n", T.stringof); // See also: std.traits.fullyQualifiedName
                static foreach (idx, field; T.tupleof) {
writer.formattedWrite("\t%s: %s\n", T.tupleof[idx].stringof, this.tupleof[idx]);
                }
                put(writer, ")");
        }
}

struct Foo {
        int x, y;
        string s;
        mixin ToStringMixin;
}

void main() {
        auto foo = Foo(3, 4, "hello");
        writeln(foo);
}

```

Note however that the templated version of toString(W) can be difficult to debug in some cases as, if it fails to compile, std.format will simply ignore it and not use it while the rest of the program compiles successfully. Any compilation error message can be seen by instead attempting to call the method directly, e.g. something like `auto a = appender!string; foo.toString(a);`. I don't use the delegate version personally, but if that's already working for you, may as well stick with it.

If you wanted to avoid including a mixin in all of your structs, another option is to create a generic templated container struct with its own toString:

```d
struct ToStringer(T) {
        T t; // Consider T* t
        void toString(W)(ref W writer) {
                //assert(t !is null);
                writer.formattedWrite("%s(\n", T.stringof);
                static foreach (idx, field; T.tupleof) {
writer.formattedWrite("\t%s: %s\n", T.tupleof[idx].stringof, t.tupleof[idx]);
                }
                put(writer, ")");
        }
}
auto ToString(T)(ref T t) { // syntactic sugar
        return ToStringer!T(t);
}

struct Foo {
        int x, y;
        string s;
}


void main() {
        auto foo = Foo(3, 4, "hello");
        //writeln(ToStringer!Foo(foo));
        writeln(foo.ToString);
}
```

Reply via email to