Thread overview | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
November 04, 2013 Copy elision by spec | ||||
---|---|---|---|---|
| ||||
I was quite surprised to see that the following program compiles just fine with DMD: struct S { @disable this(this); int n; } S createS(int i) { S s; s.n = i; return s; } void main(string[] args) { auto foo = createS(1); foo = createS(2); } I already knew that the compiler was allowed to elide copies on return from functions, but I thought this was an optimisation, and not part of the language proper. I would have expected the compiler to complain that createS() can't return an S since S's postblit constructor is disabled. My question is therefore, is this by design? Can I rely on this to work in the future, and on all compilers? If this is the case, it really should be added to the spec. (Or maybe it's there already, but I couldn't find it.) Lars |
November 04, 2013 Re: Copy elision by spec | ||||
---|---|---|---|---|
| ||||
Posted in reply to Lars T. Kyllingstad | On Monday, 4 November 2013 at 07:02:26 UTC, Lars T. Kyllingstad wrote: > My question is therefore, is this by design? Can I rely on this to work in the future, and on all compilers? If this is the case, it really should be added to the spec. (Or maybe it's there already, but I couldn't find it.) > > Lars Funny you should ask: http://d.puremagic.com/issues/show_bug.cgi?id=11287 According to the conversation, NRVO is supposed to be part of the spec, and you should expect it to work. |
November 04, 2013 Re: Copy elision by spec | ||||
---|---|---|---|---|
| ||||
Posted in reply to Lars T. Kyllingstad | On Monday, 4 November 2013 at 07:02:26 UTC, Lars T. Kyllingstad wrote:
> I was quite surprised to see that the following program compiles just fine with DMD:
>
> struct S
> {
> @disable this(this);
> int n;
> }
>
> S createS(int i)
> {
> S s;
> s.n = i;
> return s;
> }
>
> void main(string[] args)
> {
> auto foo = createS(1);
> foo = createS(2);
> }
>
> I already knew that the compiler was allowed to elide copies on return from functions, but I thought this was an optimisation, and not part of the language proper. I would have expected the compiler to complain that createS() can't return an S since S's postblit constructor is disabled.
>
> My question is therefore, is this by design? Can I rely on this to work in the future, and on all compilers? If this is the case, it really should be added to the spec. (Or maybe it's there already, but I couldn't find it.)
>
> Lars
My understanding is that your example illustrates a *move*, not a *copy*. AFAICT, non-copyable structs would be next to useless if we couldn't move them.
|
November 04, 2013 Re: Copy elision by spec | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jakob Ovrum | On Monday, 4 November 2013 at 09:42:53 UTC, Jakob Ovrum wrote:
> On Monday, 4 November 2013 at 07:02:26 UTC, Lars T. Kyllingstad wrote:
>> I was quite surprised to see that the following program compiles just fine with DMD:
>>
>> struct S
>> {
>> @disable this(this);
>> int n;
>> }
>>
>> S createS(int i)
>> {
>> S s;
>> s.n = i;
>> return s;
>> }
>>
>> void main(string[] args)
>> {
>> auto foo = createS(1);
>> foo = createS(2);
>> }
>>
>> I already knew that the compiler was allowed to elide copies on return from functions, but I thought this was an optimisation, and not part of the language proper. I would have expected the compiler to complain that createS() can't return an S since S's postblit constructor is disabled.
>>
>> My question is therefore, is this by design? Can I rely on this to work in the future, and on all compilers? If this is the case, it really should be added to the spec. (Or maybe it's there already, but I couldn't find it.)
>>
>> Lars
>
> My understanding is that your example illustrates a *move*, not a *copy*. AFAICT, non-copyable structs would be next to useless if we couldn't move them.
I know, and I agree. The question is whether this is a move *by specification*, i.e. whether the language makes a guarantee that return values are always moved under certain circumstances. If so, this should be mentioned in the spec, along with a detailed description of said circumstances.
I am using this "feature" in a program I'm working on right now. It would be a shame if this is a mere DMD artifact, as opposed to a language feature, because then I can't depend on it working in other compilers or in future DMD versions. I really don't know any other way to solve my problem either, so I'm keeping my fingers crossed that this can become part of the official spec. For anyone interested, the actual use case is a no-arguments constructor for a non-copyable struct, emulated with static opCall():
struct Foo
{
// "Constructor"
static Foo opCall()
{
Foo f;
// Initialize f.
return f;
}
// Foo should not be copyable.
@disable this(this);
}
// Construct a new Foo
auto foo = Foo();
|
November 04, 2013 Re: Copy elision by spec | ||||
---|---|---|---|---|
| ||||
Posted in reply to Lars T. Kyllingstad Attachments:
| 2013/11/4 Lars T. Kyllingstad <public@kyllingen.net>
> On Monday, 4 November 2013 at 09:42:53 UTC, Jakob Ovrum wrote:
>
>> On Monday, 4 November 2013 at 07:02:26 UTC, Lars T. Kyllingstad wrote:
>>
>>> I was quite surprised to see that the following program compiles just fine with DMD:
>>>
>>> struct S
>>> {
>>> @disable this(this);
>>> int n;
>>> }
>>>
>>> S createS(int i)
>>> {
>>> S s;
>>> s.n = i;
>>> return s;
>>> }
>>>
>>> void main(string[] args)
>>> {
>>> auto foo = createS(1);
>>> foo = createS(2);
>>> }
>>>
>>> I already knew that the compiler was allowed to elide copies on return from functions, but I thought this was an optimisation, and not part of the language proper. I would have expected the compiler to complain that createS() can't return an S since S's postblit constructor is disabled.
>>>
>>> My question is therefore, is this by design? Can I rely on this to work in the future, and on all compilers? If this is the case, it really should be added to the spec. (Or maybe it's there already, but I couldn't find it.)
>>>
>>> Lars
>>>
>>
>> My understanding is that your example illustrates a *move*, not a *copy*. AFAICT, non-copyable structs would be next to useless if we couldn't move them.
>>
>
> I know, and I agree. The question is whether this is a move *by specification*, i.e. whether the language makes a guarantee that return values are always moved under certain circumstances. If so, this should be mentioned in the spec, along with a detailed description of said circumstances.
>
> I am using this "feature" in a program I'm working on right now. It would be a shame if this is a mere DMD artifact, as opposed to a language feature, because then I can't depend on it working in other compilers or in future DMD versions. I really don't know any other way to solve my problem either, so I'm keeping my fingers crossed that this can become part of the official spec. For anyone interested, the actual use case is a no-arguments constructor for a non-copyable struct, emulated with static opCall():
>
> struct Foo
> {
> // "Constructor"
> static Foo opCall()
> {
> Foo f;
> // Initialize f.
> return f;
> }
>
> // Foo should not be copyable.
> @disable this(this);
> }
>
> // Construct a new Foo
> auto foo = Foo();
>
I think it should be properly mentioned in language spec. Otherwise, we cannot keep std.typecons.scoped in standard library.
Kenji Hara
|
November 04, 2013 Re: Copy elision by spec | ||||
---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra | On Monday, 4 November 2013 at 07:17:12 UTC, monarch_dodra wrote:
> http://d.puremagic.com/issues/show_bug.cgi?id=11287
>
> According to the conversation, NRVO is supposed to be part of the spec, and you should expect it to work.
I'm not an expert, but aren't there cases where NRVO can't be applied? For example:
S foo()
{
S s1;
// Initialize s1
S s2;
// Initialize s2
if (someCondition) return s1;
else return s2;
}
However, the return value can always be *moved*.
|
November 04, 2013 Re: Copy elision by spec | ||||
---|---|---|---|---|
| ||||
Posted in reply to Lars T. Kyllingstad | On Monday, 4 November 2013 at 11:41:04 UTC, Lars T. Kyllingstad wrote: > On Monday, 4 November 2013 at 07:17:12 UTC, monarch_dodra wrote: >> http://d.puremagic.com/issues/show_bug.cgi?id=11287 >> >> According to the conversation, NRVO is supposed to be part of the spec, and you should expect it to work. > > I'm not an expert, but aren't there cases where NRVO can't be applied? For example: > > S foo() > { > S s1; > // Initialize s1 > S s2; > // Initialize s2 > if (someCondition) return s1; > else return s2; > } > > However, the return value can always be *moved*. According to Andrei (http://video.ch9.ms/sessions/gonat/2013/AndreiQuickCodeGn13.zip slide 37), NRVO requires "All paths return same local". If not, "assume an extra copy". IMO "assume" means that the compiler *may* elide the copy, but *that* would be an optimization. If all your paths return the same named local, then NRVO should be guaranteed. But I think the spec should formalize the behavior. |
November 04, 2013 Re: Copy elision by spec | ||||
---|---|---|---|---|
| ||||
Posted in reply to Lars T. Kyllingstad | On 11/04/2013 03:23 AM, Lars T. Kyllingstad wrote: > On Monday, 4 November 2013 at 09:42:53 UTC, Jakob Ovrum wrote: >> My understanding is that your example illustrates a *move*, not a >> *copy*. AFAICT, non-copyable structs would be next to useless if we >> couldn't move them. > > I know, and I agree. The question is whether this is a move *by > specification*, i.e. whether the language makes a guarantee that return > values are always moved under certain circumstances. If so, this should > be mentioned in the spec, along with a detailed description of said > circumstances. I thought so too. So, I prepared the talk "Copy and Move Semantics in D" where 'move' is described as a fundamental struct operation. I presented the talk at the presence of Walter, Andrei, and other D experts and nobody objected! :p (I hope not merely because they were being polite.) http://dconf.org/2013/talks/cehreli.html Ali |
November 04, 2013 Re: Copy elision by spec | ||||
---|---|---|---|---|
| ||||
Posted in reply to Lars T. Kyllingstad | On Monday, 4 November 2013 at 11:23:33 UTC, Lars T. Kyllingstad wrote:
> I know, and I agree. The question is whether this is a move *by specification*, i.e. whether the language makes a guarantee that return values are always moved under certain circumstances. If so, this should be mentioned in the spec, along with a detailed description of said circumstances.
>
In D, structs are movable by spec. It means internal pointer and other stuff like that are incorrect by spec.
|
November 05, 2013 Re: Copy elision by spec | ||||
---|---|---|---|---|
| ||||
Posted in reply to deadalnix | On Monday, 4 November 2013 at 19:55:50 UTC, deadalnix wrote:
>
> In D, structs are movable by spec. It means internal pointer and other stuff like that are incorrect by spec.
"Structs are movable" != "returned structs are guaranteed to be moved".
|
Copyright © 1999-2021 by the D Language Foundation