digitalmars.D.learn - Generate toString() method at compile time
- Ary Borenszweig (24/24) Mar 26 2014 Hi,
- bearophile (4/6) Mar 26 2014 You can try to filter the results of getAllMembers.
- Adam D. Ruppe (19/21) Mar 26 2014 Try this:
- Ary Borenszweig (2/21) Mar 26 2014 Thanks! That's pretty neat. It seems I was missing "tupleof".
- Adam D. Ruppe (6/7) Mar 26 2014 Yea, there's other options too like __traits(derivedMembers)
- Ary Borenszweig (5/24) Mar 26 2014 A small question: tupleof seems to return a tuple of values. So
- ketmar (33/33) Mar 26 2014 that's what i did in a hurry. it seems to work, but the code is
- Adam D. Ruppe (12/13) Mar 26 2014 Most accurately, it returns a tuple of variables (it is a bit
Hi, I'd like to generate a toString() method for my classes. For example: --- import std.stdio; class Foo { int x; int y; // mixin ...? } void main() { auto foo = new Foo; foo.x = 1; foo.y = 2; writeln(foo); // prints "Foo(x = 1, y = 2)" } --- I tried using getAllMembers, but that also gives me all methods of Foo. I just want the fields. I also tried FieldTypeTuple (http://dlang.org/phobos/std_traits.html#FieldTypeTuple) but I get that gives me the types. And then I can't find anything else in std.traits that could help me. Is this possible? Thanks, Ary
Mar 26 2014
Ary Borenszweig:I tried using getAllMembers, but that also gives me all methods of Foo. I just want the fields.You can try to filter the results of getAllMembers. Bye, bearophile
Mar 26 2014
On Wednesday, 26 March 2014 at 14:16:08 UTC, Ary Borenszweig wrote:I'd like to generate a toString() method for my classes. For example:Try this: override string toString() { import std.conv; string s; s ~= this.classinfo.name ~ "("; foreach(idx, val; this.tupleof) { if(idx) s ~= ", "; s ~= this.tupleof[idx].stringof[5 .. $]; s ~= " = "; s ~= to!string(val); } s ~= ")"; return s; } add that method to Foo. $ ./test58 test58.Foo(x = 1, y = 2)
Mar 26 2014
On 3/26/14, 11:47 AM, Adam D. Ruppe wrote:On Wednesday, 26 March 2014 at 14:16:08 UTC, Ary Borenszweig wrote:Thanks! That's pretty neat. It seems I was missing "tupleof".I'd like to generate a toString() method for my classes. For example:Try this: override string toString() { import std.conv; string s; s ~= this.classinfo.name ~ "("; foreach(idx, val; this.tupleof) { if(idx) s ~= ", "; s ~= this.tupleof[idx].stringof[5 .. $]; s ~= " = "; s ~= to!string(val); } s ~= ")"; return s; } add that method to Foo. $ ./test58 test58.Foo(x = 1, y = 2)
Mar 26 2014
On Wednesday, 26 March 2014 at 14:53:55 UTC, Ary Borenszweig wrote:Thanks! That's pretty neat. It seems I was missing "tupleof".Yea, there's other options too like __traits(derivedMembers) if(!is(__traits(getMember...)) == function) and stuff like that, filtering like bearophile said, I just think tupleof is the easiest option for this.
Mar 26 2014
On 3/26/14, 11:47 AM, Adam D. Ruppe wrote:On Wednesday, 26 March 2014 at 14:16:08 UTC, Ary Borenszweig wrote:A small question: tupleof seems to return a tuple of values. So this.tupleof[idx] would return a value. However when you do this.tupleof[idx].stringof that somehow gets the name of the field. Shouldn't it return the name of the value? I'm confused.I'd like to generate a toString() method for my classes. For example:Try this: override string toString() { import std.conv; string s; s ~= this.classinfo.name ~ "("; foreach(idx, val; this.tupleof) { if(idx) s ~= ", "; s ~= this.tupleof[idx].stringof[5 .. $]; s ~= " = "; s ~= to!string(val); } s ~= ")"; return s; } add that method to Foo. $ ./test58 test58.Foo(x = 1, y = 2)
Mar 26 2014
that's what i did in a hurry. it seems to work, but the code is very ugly. [/code] import std.conv, std.stdio, std.string, std.traits; string gen_printer (alias cn) () { string res = "override string toString () {\nstring res = `" ~ cn.stringof ~ "(`;\n"; bool need_comma = false; foreach (i, m; __traits(derivedMembers, cn)) { static if (!isCallable!(__traits(getMember, cn, m)) /*&& m != "Monitor"*/) { if (need_comma) res ~= `res ~= ", ";`; else need_comma = true; res ~= "res~=`" ~ m ~ " = `~to!string(" ~ m ~ ");"; } } res ~= "res~=`)`;\n"; res ~= "return res;\n}\n"; return res; } class Foo { int x; int y; void test () {} mixin(gen_printer!Foo); } void main () { auto foo = new Foo; foo.x = 1; foo.y = 2; writefln("%s", foo); // prints "Foo(x = 1, y = 2)" } [/code]
Mar 26 2014
On Wednesday, 26 March 2014 at 15:01:35 UTC, Ary Borenszweig wrote:A small question: tupleof seems to return a tuple of values.Most accurately, it returns a tuple of variables (it is a bit magical). So struct A { int a; string b; } the tupleof there is int a; string b - variables with different types and different names. The stringof works as if you said A.a.stringof - it fetches the name of the variable. The slice I did on it cuts off the "this." from the full name, leaving just the name. Value to string is done with the to!string function, .stringof always works at compile time.
Mar 26 2014