Bug 4266 – add support for structs in std.format.doFormat

Status
RESOLVED
Resolution
WORKSFORME
Severity
enhancement
Priority
P2
Component
phobos
Product
D
Version
D2
Platform
All
OS
All
Creation time
2010-06-03T14:08:00Z
Last change time
2014-09-19T22:01:45Z
Assigned to
nobody
Creator
hoganmeier

Comments

Comment #0 by hoganmeier — 2010-06-03T14:08:16Z
Currently there is a check if a struct has a toString member and it fails if not. It is really cumbersome to code a toString() by hand for every little struct. if (tis.xtoString is null) throw new FormatError("Can't convert " ~ tis.toString() ~ " to string: \"string toString()\" not defined"); s = tis.xtoString(argptr); Especially if you are dealing with external headers (in my case Windows/DirectX headers) you have to face lots of structures that don't have a toString method. Please add support for a default struct toString that uses the "{membername: value, member2:value, member3:{mm1:v, ....}}" style just like arrays are formatted as "[a, b, c, d,...]" and AAs as "[k1:v1, k2:v2, ..]" by default. ==> if (tis.xtoString is null) putStruct(....); else s = tis.xtoString(argptr);
Comment #1 by hoganmeier — 2010-06-03T14:42:23Z
This is an (inefficient) workaround, but it does its job until this is fixed. import std.string : format; string myformat(T...)(T ts) { string res; foreach (t; ts) { static if (is (typeof(t) U : U*) && !is(U == void)) // is a pointer { res ~= myformat(*t); } else static if (is (typeof(t) == struct)) { res ~= "{"; foreach(i, el; t.tupleof) { res ~= t.tupleof[i].stringof[2..$] ~ ":" ~ myformat(el); // the slice cuts off the "t." that is always prepended static if (i < t.tupleof.length-1) res ~= ", "; } res ~= "}"; } else res ~= format(t); } return res; }
Comment #2 by hoganmeier — 2010-06-03T14:51:03Z
add this branch (+ import std.traits;) else static if (isSomeString!(typeof(t))) // enclose a string in "" res ~= `"` ~ t ~ `"`; and it nearly matches the C struct intialization style (except for pointers, then you need to remove the first branch): struct S { int a; S2* p; S2 adad; } struct S2 { byte[4] aaaa = [0,1,2,3]; string ddd = "asd"; } void main() { S2 sss = S2([5,4,5,4], "foo"); S s = S(2, &sss); write(myformat(s)); } gives: {a:2, p:{aaaa:[5,4,5,4], ddd:"foo"}, adad:{aaaa:[0,1,2,3], ddd:"asd"}}
Comment #3 by andrej.mitrovich — 2013-02-18T10:08:30Z
Did the code used to just fail to compile before? Now it prints the values: import std.string; import std.stdio; struct S { int x; float y; string z; } void main() { string s = format("%s", S()); writeln(s); } > S(0, nan, "") If that's good enough you can close with "WORKSFORME", thanks.
Comment #4 by hsteoh — 2014-09-19T22:01:45Z
Since there's no response, I'm closing this bug as worksforme (also just confirmed that it works on git HEAD on Linux 64-bit). If there is still a problem, please reopen this bug. Thanks! Note that doFormat is a very old function that's basically no longer used these days; std.format correctly handles the formatting of structs.