digitalmars.D - toString() on struct template
- Henning Hasemann (23/23) Feb 28 2007 I have a struct template with just 2 data members
- Reiner Pope (5/44) Feb 28 2007 I couldn't get your code to work as is, because it wasn't a 'static'
- Henning Hasemann (4/6) Feb 28 2007 sorry, I just forgot to copy the static. The opCall itself seems to work...
- mario pernici (10/39) Feb 28 2007 It works in this example
- Henning Hasemann (4/4) Feb 28 2007 Hm, if I just break it down to that small example it works at expected,
- endea (2/7) Feb 28 2007 "%d" formats int type, that might be problem for Vector2d!(other-than-in...
- Henning Hasemann (12/12) Feb 28 2007 I think I got it now:
- Daniel Keep (35/51) Mar 01 2007 You mentioned a library... If I remember correctly (standard
- Henning Hasemann (9/66) Mar 01 2007 Sounds logical to me, but atm the only type I use for T is int
- Henning Hasemann (12/28) Mar 01 2007 The more I play around with my code the more I think you are right.
- Daniel Keep (11/41) Mar 01 2007 I think the best explanation in that case would be: "I was wrong." It
- Henning Hasemann (23/26) Mar 02 2007 Hm okay it has nothing to do with templates it seems, I implemented
- Henning Hasemann (5/5) Mar 02 2007 Now it seems to me, the problem is when calling format().
- Henning Hasemann (34/41) Mar 02 2007 It gets stranger more and more.
- Thomas Kuehne (13/25) Mar 02 2007 -----BEGIN PGP SIGNED MESSAGE-----
- Henning Hasemann (11/11) Mar 02 2007 You where right from the beginning.
I have a struct template with just 2 data members (thats why I'd actually preferred a struct over a class). It implements several methods such as overloaded operators and the pseudo constructor roughly like this: struct Vector2d(T) { T x, y; Vector2d!(T) opCall(T x, T y) { Vector2d!(T) v; v.x = x; v.y = y; return v; } char[] toString() { return format("(%d|%d)", x, y); } } But the toString actually crashes hard everytime *before* the format-call. (Btw: Dont be afraid because of the %d's I actually only instantiate the template with int for testing). Is there something wrong with my understanding or with the compiler (tested dmd 1.005 and 1.007)? Whats the proper way of implementing toString vor structs if not like this? Henning
Feb 28 2007
Henning Hasemann wrote:I have a struct template with just 2 data members (thats why I'd actually preferred a struct over a class). It implements several methods such as overloaded operators and the pseudo constructor roughly like this: struct Vector2d(T) { T x, y; Vector2d!(T) opCall(T x, T y) { Vector2d!(T) v; v.x = x; v.y = y; return v; } char[] toString() { return format("(%d|%d)", x, y); } }I couldn't get your code to work as is, because it wasn't a 'static' opCall. The following code, however, runs fine on my computer:import std.stdio; import std.string; struct Vector2d(T) { T x, y; static Vector2d!(T) opCall(T x, T y) { Vector2d!(T) v; v.x = x; v.y = y; return v; } char[] toString() { return format("(%d|%d)", x, y); } } void main() { auto a = Vector2d!(int)(5, 6); writefln(a.toString()); }Hope that helps, Reiner
Feb 28 2007
On Thu, 01 Mar 2007 08:01:37 +1100 Reiner Pope <reIGNOREiner.poCAPSpe gmFOOail.cBARom> wrote:I couldn't get your code to work as is, because it wasn't a 'static' opCall. The following code, however, runs fine on my computer:sorry, I just forgot to copy the static. The opCall itself seems to work just fine. Henning
Feb 28 2007
Henning Hasemann Wrote:I have a struct template with just 2 data members (thats why I'd actually preferred a struct over a class). It implements several methods such as overloaded operators and the pseudo constructor roughly like this: struct Vector2d(T) { T x, y; Vector2d!(T) opCall(T x, T y) { Vector2d!(T) v; v.x = x; v.y = y; return v; } char[] toString() { return format("(%d|%d)", x, y); } } But the toString actually crashes hard everytime *before* the format-call. (Btw: Dont be afraid because of the %d's I actually only instantiate the template with int for testing). Is there something wrong with my understanding or with the compiler (tested dmd 1.005 and 1.007)? Whats the proper way of implementing toString vor structs if not like this? HenningIt works in this example void main() { Vector2d!(int) a; auto b = a(5,6); writefln(b); } output: (5|6) Mario
Feb 28 2007
Hm, if I just break it down to that small example it works at expected, so my bug has to be somewhere else, sorry for bothering you before testing the minimal code myself. Henning
Feb 28 2007
Henning Hasemann kirjoitti:Hm, if I just break it down to that small example it works at expected, so my bug has to be somewhere else, sorry for bothering you before testing the minimal code myself. Henning"%d" formats int type, that might be problem for Vector2d!(other-than-int)
Feb 28 2007
I think I got it now: If you build the source together with the main function, there is no problem. However in my constellation (the struct an the code that calls toString in a linux static library which is linked against a main function) this error occurs. The stacktrace says something about TypeInfo IIRC. So it seems this information gets lost somehow? I use dmd-1.007 (tried with 1.005 too), build the library with rebuild-0.12. Maybe I should say that I use derelict too, but the error also occurs when toString is called before any derelict-function. I will try to further reduce the example, maybe later today. Henning
Feb 28 2007
Henning Hasemann wrote:I think I got it now: If you build the source together with the main function, there is no problem. However in my constellation (the struct an the code that calls toString in a linux static library which is linked against a main function) this error occurs. The stacktrace says something about TypeInfo IIRC. So it seems this information gets lost somehow? I use dmd-1.007 (tried with 1.005 too), build the library with rebuild-0.12. Maybe I should say that I use derelict too, but the error also occurs when toString is called before any derelict-function. I will try to further reduce the example, maybe later today. HenningYou mentioned a library... If I remember correctly (standard disclaimers apply), then templates are NOT compiled into a library. For example, let's say you compiled the following file into a library: struct Foo(T) { void bar(T value) { writefln("%s", value); } } And then used it like so: void main() { Foo!(int) x; x.bar(42); } And finally compiled it like thus: dmd FooLib.lib main.d This would fail since FooLib.lib doesn't actually *have* the implementation of Foo in it. In order for D to compile a templated struct or class into a library, it would need to compile it for every possible type, which obviously isn't going to happen. If you want to use templates in a library, you *need* to ship and compile against the source code, not against a precompiled library. The one exception to this is that it should work for any templates you've explicitly instantiated. So, if you append this to Foo's source file: alias Foo!(int) FooInt; then it should work. -- Daniel -- Unlike Knuth, I have neither proven or tried the above; it may not even make sense. v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/
Mar 01 2007
On Thu, 01 Mar 2007 21:20:38 +1100 Daniel Keep <daniel.keep.lists gmail.com> wrote:Henning Hasemann wrote:Sounds logical to me, but atm the only type I use for T is int and the template is instantiated in the library so the version used should be implemented. Calling other methods seems to work, too.I think I got it now: If you build the source together with the main function, there is no problem. However in my constellation (the struct an the code that calls toString in a linux static library which is linked against a main function) this error occurs. The stacktrace says something about TypeInfo IIRC. So it seems this information gets lost somehow? I use dmd-1.007 (tried with 1.005 too), build the library with rebuild-0.12. Maybe I should say that I use derelict too, but the error also occurs when toString is called before any derelict-function. I will try to further reduce the example, maybe later today. HenningYou mentioned a library... If I remember correctly (standard disclaimers apply), then templates are NOT compiled into a library. For example, let's say you compiled the following file into a library: struct Foo(T) { void bar(T value) { writefln("%s", value); } } And then used it like so: void main() { Foo!(int) x; x.bar(42); } And finally compiled it like thus: dmd FooLib.lib main.d This would fail since FooLib.lib doesn't actually *have* the implementation of Foo in it. In order for D to compile a templated struct or class into a library, it would need to compile it for every possible type, which obviously isn't going to happen.If you want to use templates in a library, you *need* to ship and compile against the source code, not against a precompiled library. The one exception to this is that it should work for any templates you've explicitly instantiated. So, if you append this to Foo's source file: alias Foo!(int) FooInt; then it should work.And that's what I'm doing, too. So no problem here. Ill now start to find a minimal example of the problem. Henning
Mar 01 2007
OAnd finally compiled it like thus: dmd FooLib.lib main.d This would fail since FooLib.lib doesn't actually *have* the implementation of Foo in it. In order for D to compile a templated struct or class into a library, it would need to compile it for every possible type, which obviously isn't going to happen.The more I play around with my code the more I think you are right. But I dont understand why I dont get an error at compile time but at runtime? Shouldnt the compiler already see if the template instantiation is available or not in the linking step?If you want to use templates in a library, you *need* to ship and compile against the source code, not against a precompiled library. The one exception to this is that it should work for any templates you've explicitly instantiated. So, if you append this to Foo's source file: alias Foo!(int) FooInt; then it should work.The problem occurs also when the "main module" does not call any template function but only code from inside the library does. Can you explain that with your theory? What would be the solution? Henning
Mar 01 2007
Henning Hasemann wrote:OYes, it should... I thought these were link errors, which leads me to...And finally compiled it like thus: dmd FooLib.lib main.d This would fail since FooLib.lib doesn't actually *have* the implementation of Foo in it. In order for D to compile a templated struct or class into a library, it would need to compile it for every possible type, which obviously isn't going to happen.The more I play around with my code the more I think you are right. But I dont understand why I dont get an error at compile time but at runtime? Shouldnt the compiler already see if the template instantiation is available or not in the linking step?I think the best explanation in that case would be: "I was wrong." It was something of a long-shot, stab in the dark guess... Sorry. -- Daniel -- Unlike Knuth, I have neither proven or tried the above; it may not even make sense. v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/If you want to use templates in a library, you *need* to ship and compile against the source code, not against a precompiled library. The one exception to this is that it should work for any templates you've explicitly instantiated. So, if you append this to Foo's source file: alias Foo!(int) FooInt; then it should work.The problem occurs also when the "main module" does not call any template function but only code from inside the library does. Can you explain that with your theory? What would be the solution? Henning
Mar 01 2007
On Fri, 02 Mar 2007 12:32:22 +1100 Daniel Keep <daniel.keep.lists gmail.com> wrote:I think the best explanation in that case would be: "I was wrong." It was something of a long-shot, stab in the dark guess...Hm okay it has nothing to do with templates it seems, I implemented my speciasization "Point" directly as struct (not as a special template implementation) and it produces the same error at run time. The traces always look like this: (this=0xbf92921c) at vector2d.d:170 Previous frame inner to this frame (corrupt stack?) Also I did not manage to reduce this to some presentable code piece, when I start from ground I dont manage to get this error. Arr, I hate this kind of problems, feels like C where a fault somewhere causes misbehaviour somewhere else. But why is the problem just there? The rest of the code happily calls methods everywhere and works. Very strange thing. Henning -- v4sw7Yhw4ln0pr7Ock2/3ma7uLw5Xm0l6/7DGKi2e6t6ELNSTVXb7AHIMOen5a2Xs5Mr2g5ACPR hackerkey.com
Mar 02 2007
Now it seems to me, the problem is when calling format(). (I thought I exchanged format() before with a simple string without result, strange again). -- v4sw7Yhw4ln0pr7Ock2/3ma7uLw5Xm0l6/7DGKi2e6t6ELNSTVXb7AHIMOen5a2Xs5Mr2g5ACPR hackerkey.com
Mar 02 2007
On Fri, 2 Mar 2007 09:53:03 +0100 Henning Hasemann <hhasemann web.de> wrote:Now it seems to me, the problem is when calling format(). (I thought I exchanged format() before with a simple string without result, strange again). -- v4sw7Yhw4ln0pr7Ock2/3ma7uLw5Xm0l6/7DGKi2e6t6ELNSTVXb7AHIMOen5a2Xs5Mr2g5ACPR hackerkey.comIt gets stranger more and more. I added a method to my vector2d struct template: (line numbers included) 92 char[] my_to_string() { 93 writefln(x); 94 return "(" ~ .toString(x) ~ "|" ~ .toString(y) ~ ")"; 95 } (I wanted to be sure the problem is not somewhere around foo.toString vs toString(foo)) x and y are members of the struct. The writefln prints the correct x value, so I think the template must have been correctly instantiated and this exists and is correct. But the return statement crashes like this: Program received signal SIGSEGV, Segmentation fault. [Switching to Thread -1209821504 (LWP 3999)] 0xb7ea69cc in memcpy () from /lib/tls/i686/cmov/libc.so.6 (gdb) bt 12my_to_stringMFZAa (this=0xbf81110c) at vector2d.d:94 Previous frame inner to this frame (corrupt stack?) indiana is the name of the library and the module is vector2d. test.d is the module that holds main and calls my_to_string. It also seems when I at writefln("some_const_string") at the beginning of my_to_string, it crashes at an internal function called doFormat. Im getting crazy with this strange thing, I'd be happy about any small hint what I could do. Henning -- v4sw7Yhw4ln0pr7Ock2/3ma7uLw5Xm0l6/7DGKi2e6t6ELNSTVXb7AHIMOen5a2Xs5Mr2g5ACPR hackerkey.com
Mar 02 2007
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Henning Hasemann schrieb am 2007-03-02: [snip]But the return statement crashes like this: Program received signal SIGSEGV, Segmentation fault. [Switching to Thread -1209821504 (LWP 3999)] 0xb7ea69cc in memcpy () from /lib/tls/i686/cmov/libc.so.6 (gdb) bt 12my_to_stringMFZAa (this=0xbf81110c) at vector2d.d:94 Previous frame inner to this frame (corrupt stack?)Please use the following command to get the corret stack trace: objcopy -R .debug_frame original-binary fixed-binary http://d.puremagic.com/issues/show_bug.cgi?id=136#c6 Thomas -----BEGIN PGP SIGNATURE----- iD8DBQFF6CU8LK5blCcjpWoRAiHuAJ4hHUSfBWyJ9zWTOWnrG6ItqJsRjgCfS+Op 9nYgVZYmDiWK9FfZUopV4HA= =kbea -----END PGP SIGNATURE-----
Mar 02 2007
You where right from the beginning. In another module in the same library there was an instantiation of the template with real, which natuarally wasnt available. But its very evil that this throws an error when using the int-Version which is correctly there. Anyway this should really be detected at compile/link - time, since it is hard to track down. Thanks for your time to anybody :-) Henning -- v4sw7Yhw4ln0pr7Ock2/3ma7uLw5Xm0l6/7DGKi2e6t6ELNSTVXb7AHIMOen5a2Xs5Mr2g5ACPR hackerkey.com
Mar 02 2007