digitalmars.D - std.algorithm move() struct emptying
- Torarin (6/6) Aug 29 2010 Hi,
- Stanislav Blinov (13/22) Aug 29 2010 I may be wrong, but it seems that in this case T.init will yield a
- Torarin (5/26) Aug 29 2010 Yes, you are right!
- Andrei Alexandrescu (3/9) Aug 29 2010 T.init is not guaranteed to be an lvalue.
- Torarin (3/15) Aug 29 2010 Even in this case, or in some special case?
- Jonathan M Davis (5/23) Aug 30 2010 T.init cannot be set. It's a fixed value. When you use it, you're typica...
- Torarin (7/30) Aug 30 2010 Currently you can take its address, so doesn't that mean that it's an lv...
- Stanislav Blinov (19/26) Aug 30 2010 aren't
- Torarin (6/10) Aug 30 2010 Yeah, I get the enum case, but what I forgot to mention is that the
- Stanislav Blinov (2/6) Aug 31 2010 I don't know, maybe the one that's not invented yet ;)
- bearophile (4/22) Aug 31 2010 If in generic code T.init is not guaranteed to be an lvalue, as your exa...
- Michel Fortin (9/12) Aug 31 2010 Personally, I'd say the code should check if T.init is an lvalue using
- Stanislav Blinov (14/22) Aug 31 2010 Well, currently there's even nastier thing than syntax error.
- Andrei Alexandrescu (4/12) Aug 31 2010 I recall I wrote that code to avoid a compiler bug when T == Tuple!(some...
- Philippe Sigaud (5/21) Aug 31 2010 Is that related to this bug?
- Andrei Alexandrescu (3/26) Aug 31 2010 Very possible.
Hi, in std.algorithm move(), this is the operation used to set the source of a struct move to .init: static T empty; memcpy(&source, &empty, T.sizeof); Is there any particular reason why the more compact &T.init is not used?
Aug 29 2010
Torarin wrote:Hi, in std.algorithm move(), this is the operation used to set the source of a struct move to .init: static T empty; memcpy(&source, &empty, T.sizeof); Is there any particular reason why the more compact &T.init is not used?I may be wrong, but it seems that in this case T.init will yield a temporary, while static T empty is 'always' there. Consider: struct S {} void main() { writefln("%x", &S.init); // prints one value writefln("%x", &S.init); // prints another value static S s; writefln("%x", &s); // prints one value writefln("%x", &s); // prints the same value }
Aug 29 2010
Yes, you are right! Looking at the assembly, T.init creates a struct on the stack. 2010/8/29 Stanislav Blinov <stanislav.blinov gmail.com>Torarin wrote:a struct move to .init:Hi, in std.algorithm move(), this is the operation used to set the source of=ary, while static T empty is 'always' there.=A0static T empty; =A0memcpy(&source, &empty, T.sizeof); Is there any particular reason why the more compact &T.init is not used?I may be wrong, but it seems that in this case T.init will yield a tempor=Consider: struct S {} void main() { =A0 =A0 =A0 =A0writefln("%x", &S.init); // prints one value =A0 =A0 =A0 =A0writefln("%x", &S.init); // prints another value =A0 =A0 =A0 =A0static S s; =A0 =A0 =A0 =A0writefln("%x", &s); // prints one value =A0 =A0 =A0 =A0writefln("%x", &s); // prints the same value }
Aug 29 2010
On 08/29/2010 12:00 PM, Torarin wrote:Hi, in std.algorithm move(), this is the operation used to set the source of a struct move to .init: static T empty; memcpy(&source, &empty, T.sizeof); Is there any particular reason why the more compact &T.init is not used?T.init is not guaranteed to be an lvalue. Andrei
Aug 29 2010
Even in this case, or in some special case? Torarin 2010/8/29 Andrei Alexandrescu <SeeWebsiteForEmail erdani.org>:On 08/29/2010 12:00 PM, Torarin wrote:Hi, in std.algorithm move(), this is the operation used to set the source of a struct move to .init: =A0 static T empty; =A0 memcpy(&source, &empty, T.sizeof); Is there any particular reason why the more compact &T.init is not used?T.init is not guaranteed to be an lvalue. Andrei
Aug 29 2010
On Sunday, August 29, 2010 11:51:51 Torarin wrote:Even in this case, or in some special case? Torarin 2010/8/29 Andrei Alexandrescu <SeeWebsiteForEmail erdani.org>:T.init cannot be set. It's a fixed value. When you use it, you're typically going to be copying it to an lvalue or creating a temporary. Temporaries aren't lvalues. So, T.init can be assigned to an lvalue, but it isn't itself an lvalue. - Jonathan M DavisOn 08/29/2010 12:00 PM, Torarin wrote:Hi, in std.algorithm move(), this is the operation used to set the source of a struct move to .init: static T empty; memcpy(&source, &empty, T.sizeof); Is there any particular reason why the more compact &T.init is not used?T.init is not guaranteed to be an lvalue. Andrei
Aug 30 2010
Currently you can take its address, so doesn't that mean that it's an lvalu= e? 2010/8/30 Jonathan M Davis <jmdavisprog gmail.com>:On Sunday, August 29, 2010 11:51:51 Torarin wrote:ofEven in this case, or in some special case? Torarin 2010/8/29 Andrei Alexandrescu <SeeWebsiteForEmail erdani.org>:On 08/29/2010 12:00 PM, Torarin wrote:Hi, in std.algorithm move(), this is the operation used to set the source=ed?a struct move to .init: =A0 static T empty; =A0 memcpy(&source, &empty, T.sizeof); Is there any particular reason why the more compact &T.init is not us=ly goingT.init cannot be set. It's a fixed value. When you use it, you're typical=T.init is not guaranteed to be an lvalue. Andreito be copying it to an lvalue or creating a temporary. Temporaries aren't lvalues. So, T.init can be assigned to an lvalue, but it isn't itself an =lvalue.- Jonathan M Davis
Aug 30 2010
Torarin wrote:typically goingT.init cannot be set. It's a fixed value. When you use it, you'rearen'tto be copying it to an lvalue or creating a temporary. Temporariesitself an lvalue.lvalues. So, T.init can be assigned to an lvalue, but it isn't- Jonathan M DavisCurrently you can take its address, so doesn't that mean that it's an lvalue?No, you can't. Generally, that is. For example: enum A { a, b } void main() { void* p = &A.init; // won't compile } You may be able to take address of what .init returns, but what Andrei meant by 'it is not guaranteed' means that this is not always the case. So basically, you should not rely on the cases when you can do that. That's why I was wrong, also. The case wasn't about temporaries at all :)
Aug 30 2010
Yeah, I get the enum case, but what I forgot to mention is that the example from move() is enclosed in static if (is(T == struct)) Which makes me wonder what kind of struct would have an rvalue .init. Torarin 2010/8/30 Stanislav Blinov <stanislav.blinov gmail.com>:You may be able to take address of what .init returns, but what Andrei meant by 'it is not guaranteed' means that this is not always the case. So basically, you should not rely on the cases when you can do that. That's why I was wrong, also. The case wasn't about temporaries at all :)
Aug 30 2010
31.08.2010 0:27, Torarin wrote:Yeah, I get the enum case, but what I forgot to mention is that the example from move() is enclosed in static if (is(T == struct)) Which makes me wonder what kind of struct would have an rvalue .init.I don't know, maybe the one that's not invented yet ;)
Aug 31 2010
Stanislav Blinov:If in generic code T.init is not guaranteed to be an lvalue, as your example shows, isn't it better to disallow (turning it into a syntax error) &T.init in all cases? Bye, bearophileCurrently you can take its address, so doesn't that mean that it's an lvalue?No, you can't. Generally, that is. For example: enum A { a, b } void main() { void* p = &A.init; // won't compile } You may be able to take address of what .init returns, but what Andrei meant by 'it is not guaranteed' means that this is not always the case. So basically, you should not rely on the cases when you can do that.
Aug 31 2010
On 2010-08-31 06:16:17 -0400, bearophile <bearophileHUGS lycos.com> said:If in generic code T.init is not guaranteed to be an lvalue, as your example shows, isn't it better to disallow (turning it into a syntax error) &T.init in all cases?Personally, I'd say the code should check if T.init is an lvalue using __traits(compiles, &T.init) or is(typeof(&T.init)) and avoid creating a static variable or temporary when it is. This optimization of course depends &T.init not being a syntax error. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Aug 31 2010
31.08.2010 16:49, Michel Fortin пишет:On 2010-08-31 06:16:17 -0400, bearophile <bearophileHUGS lycos.com> said:Well, currently there's even nastier thing than syntax error. struct S { int a; property static S init() { return S(10); } } Or even struct S { property static void init() {} } Personally I agree with bearophile, but maybe the code such as above should be forbidden as well, and for other builtin properties too?If in generic code T.init is not guaranteed to be an lvalue, as your example shows, isn't it better to disallow (turning it into a syntax error) &T.init in all cases?Personally, I'd say the code should check if T.init is an lvalue using __traits(compiles, &T.init) or is(typeof(&T.init)) and avoid creating a static variable or temporary when it is. This optimization of course depends &T.init not being a syntax error.
Aug 31 2010
On 8/31/10 7:49 CDT, Michel Fortin wrote:On 2010-08-31 06:16:17 -0400, bearophile <bearophileHUGS lycos.com> said:I recall I wrote that code to avoid a compiler bug when T == Tuple!(some types). AndreiIf in generic code T.init is not guaranteed to be an lvalue, as your example shows, isn't it better to disallow (turning it into a syntax error) &T.init in all cases?Personally, I'd say the code should check if T.init is an lvalue using __traits(compiles, &T.init) or is(typeof(&T.init)) and avoid creating a static variable or temporary when it is. This optimization of course depends &T.init not being a syntax error.
Aug 31 2010
On Tue, Aug 31, 2010 at 17:05, Andrei Alexandrescu < SeeWebsiteForEmail erdani.org> wrote:On 8/31/10 7:49 CDT, Michel Fortin wrote:Is that related to this bug? http://d.puremagic.com/issues/show_bug.cgi?id=4536 PhilippeOn 2010-08-31 06:16:17 -0400, bearophile <bearophileHUGS lycos.com> said: If in generic code T.init is not guaranteed to be an lvalue, as yourI recall I wrote that code to avoid a compiler bug when T == Tuple!(some types). Andreiexample shows, isn't it better to disallow (turning it into a syntax error) &T.init in all cases?Personally, I'd say the code should check if T.init is an lvalue using __traits(compiles, &T.init) or is(typeof(&T.init)) and avoid creating a static variable or temporary when it is. This optimization of course depends &T.init not being a syntax error.
Aug 31 2010
On 8/31/10 11:28 CDT, Philippe Sigaud wrote:On Tue, Aug 31, 2010 at 17:05, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org <mailto:SeeWebsiteForEmail erdani.org>> wrote: On 8/31/10 7:49 CDT, Michel Fortin wrote: On 2010-08-31 06:16:17 -0400, bearophile <bearophileHUGS lycos.com <mailto:bearophileHUGS lycos.com>> said: If in generic code T.init is not guaranteed to be an lvalue, as your example shows, isn't it better to disallow (turning it into a syntax error) &T.init in all cases? Personally, I'd say the code should check if T.init is an lvalue using __traits(compiles, &T.init) or is(typeof(&T.init)) and avoid creating a static variable or temporary when it is. This optimization of course depends &T.init not being a syntax error. I recall I wrote that code to avoid a compiler bug when T == Tuple!(some types). Andrei Is that related to this bug? http://d.puremagic.com/issues/show_bug.cgi?id=4536 PhilippeVery possible. Andrei
Aug 31 2010