December 24, 2012
On Monday, December 24, 2012 22:11:58 Dmitry Olshansky wrote:
> 12/24/2012 9:57 PM, Jonathan M Davis пишет:
> > On Monday, December 24, 2012 12:37:54 Andrei Alexandrescu wrote:
> >> An important smoking gun is C++'s min(), which is allows writing unsafe
> >> code without casts.
> >> 
> >> const int& haveANiceDay = min(4, 5);
> > 
> > But what does that have to do with const& for function parameters?
> 
> It relates directly as one may then pass the result of min to fun(const
> ref T);

But the temporary has to be kept in existence for the duration of the statement, so I don't see how that's a problem. The temporary will last as long as the function call does. Worst case, the function returns a const ref to its parameter, but either that ref is used as part of the same statement, and so the temporary continues to exist and there are no problems, or it's copied when it's assigned to a variable, and there are no problems. It's the fact that you can have a const& local variable that breaks things, and D doesn't allow that.

- Jonathan M Davis
December 24, 2012
On 12/24/12 1:05 PM, monarch_dodra wrote:
> On Monday, 24 December 2012 at 17:37:54 UTC, Andrei Alexandrescu wrote:
>> On 12/24/12 12:11 PM, Jonathan M Davis wrote:
>>> On Monday, December 24, 2012 17:55:23 Minas Mina wrote:
>>>> On Sunday, 23 December 2012 at 23:59:55 UTC, Jonathan M Davis
>>>>
>>>> wrote:
>>>>> On Monday, December 24, 2012 00:48:01 Namespace wrote:
>>>>> but Andrei is dead set against
>>>>>
>>>>> - Jonathan M Davis
>>>>
>>>> Why?
>>>
>>> He's convinced that it's caused problems for C++ and was a major
>>> mistake. You
>>> can search the newsgroup for discussions on it. The most recent one
>>> which
>>> involved Andrei was in the beta group:
>>>
>>> http://forum.dlang.org/post/4F84D6DD.5090405@digitalmars.com
>>>
>>> - Jonathan M Davis
>>
>> An important smoking gun is C++'s min(), which is allows writing
>> unsafe code without casts.
>>
>> const int& haveANiceDay = min(4, 5);
>>
>>
>> Andrei
>
> But that example actually works correctly.

No.

Andrei
December 24, 2012
On 12/24/12 12:57 PM, Jonathan M Davis wrote:
> On Monday, December 24, 2012 12:37:54 Andrei Alexandrescu wrote:
>> An important smoking gun is C++'s min(), which is allows writing unsafe
>> code without casts.
>>
>> const int&  haveANiceDay = min(4, 5);
>
> But what does that have to do with const&  for function parameters?

min takes its parameters by const ref.

Andrei
December 24, 2012
On 12/24/12 1:20 PM, Jonathan M Davis wrote:
> On Monday, December 24, 2012 22:11:58 Dmitry Olshansky wrote:
>> 12/24/2012 9:57 PM, Jonathan M Davis пишет:
>>> On Monday, December 24, 2012 12:37:54 Andrei Alexandrescu wrote:
>>>> An important smoking gun is C++'s min(), which is allows writing unsafe
>>>> code without casts.
>>>>
>>>> const int&  haveANiceDay = min(4, 5);
>>>
>>> But what does that have to do with const&  for function parameters?
>>
>> It relates directly as one may then pass the result of min to fun(const
>> ref T);
>
> But the temporary has to be kept in existence for the duration of the
> statement, so I don't see how that's a problem.

The problem occurs of course once haveANiceDay is actually used.

> The temporary will last as
> long as the function call does. Worst case, the function returns a const ref
> to its parameter, but either that ref is used as part of the same statement,
> and so the temporary continues to exist and there are no problems, or it's
> copied when it's assigned to a variable, and there are no problems. It's the
> fact that you can have a const&  local variable that breaks things, and D
> doesn't allow that.

The very binding of rvalues to const ref would allow that breakage. We can't allow that to happen.


Andrei

December 24, 2012
On Monday, December 24, 2012 13:45:10 Andrei Alexandrescu wrote:
> The very binding of rvalues to const ref would allow that breakage. We can't allow that to happen.

But it's only bound for the length of the statement. After that, the binding can no longer exist (as the binding was a function parameter). And as I understand it, temporaries only go out of scope once the statement has completed. So,

foo(bar(min(5, 7)));

wouldn't be a problem no matter what bar or foo did, because no reference to 5, 7, or the return values of any of the functions could be kept. It's being able to do

const int& i = foo(bar(min(5, 7)));

which would allow a reference to be kept around, which D disallows.

- Jonathan M Davis
December 24, 2012
On Monday, 24 December 2012 at 18:42:31 UTC, Andrei Alexandrescu wrote:
> On 12/24/12 1:05 PM, monarch_dodra wrote:
>> On Monday, 24 December 2012 at 17:37:54 UTC, Andrei Alexandrescu wrote:
>>> On 12/24/12 12:11 PM, Jonathan M Davis wrote:
>>>> On Monday, December 24, 2012 17:55:23 Minas Mina wrote:
>>>>> On Sunday, 23 December 2012 at 23:59:55 UTC, Jonathan M Davis
>>>>>
>>>>> wrote:
>>>>>> On Monday, December 24, 2012 00:48:01 Namespace wrote:
>>>>>> but Andrei is dead set against
>>>>>>
>>>>>> - Jonathan M Davis
>>>>>
>>>>> Why?
>>>>
>>>> He's convinced that it's caused problems for C++ and was a major
>>>> mistake. You
>>>> can search the newsgroup for discussions on it. The most recent one
>>>> which
>>>> involved Andrei was in the beta group:
>>>>
>>>> http://forum.dlang.org/post/4F84D6DD.5090405@digitalmars.com
>>>>
>>>> - Jonathan M Davis
>>>
>>> An important smoking gun is C++'s min(), which is allows writing
>>> unsafe code without casts.
>>>
>>> const int& haveANiceDay = min(4, 5);
>>>
>>>
>>> Andrei
>>
>> But that example actually works correctly.
>
> No.
>
> Andrei

Hum... Indeed, it takes by ref *and* returns by ref. Passing in to out a const ref is *the* smoking gun. Working with D has gotten me used to functions that take by value and return by value...

Snap. You got me.
December 24, 2012
On Monday, December 24, 2012 19:05:32 monarch_dodra wrote:
> On Monday, 24 December 2012 at 17:37:54 UTC, Andrei Alexandrescu wrote:
> > An important smoking gun is C++'s min(), which is allows
> > writing unsafe code without casts.
> > 
> > const int& haveANiceDay = min(4, 5);
> > 
> > 
> > Andrei
> 
> But that example  actually works correctly.

Um. How?

It's created a reference to a temporary, and that temporary will no longer exist once the statement has completed. So, haveANiceDay ensd up pointing to garbage. Sure, there's a decent chance that it'll give you the value of 4 initially, but there's no guarantee whatsoever that it will or that it will continue to do so, as the program is free to reuse that memory for something else. The only thing that _might_ save you is the fact that the temporary is likely higher up on the stack and therefore less likely to have its memory reused as long as haveANiceDay exists lower on the stack. I don't believe that there's any guarantee of that however. Once the statement has completed, haveANiceDay could point to anything.

- Jonathan M Davis
December 24, 2012
On Monday, December 24, 2012 20:03:24 monarch_dodra wrote:
> Hum... Indeed, it takes by ref *and* returns by ref. Passing in to out a const ref is *the* smoking gun. Working with D has gotten me used to functions that take by value and return by value...
> 
> Snap. You got me.

It wouldn't matter if the function accepted its argument by value. You'd still be returning a reference to a variable that doesn't exist anymore. If anything, it would be _worse_ if it took it by value, since the variable definitely doesn't exist anymore once the function returns in that case, whereas with a reference, it will continue to exist for the duration of the statement that the call was made in (and beyond that, if the argument was actually an lvalue - in fact with an lvalue, the code would work as unsafe is it may be). So, it's the returning by reference that's the problem, not passing by reference.

- Jonathan M Davis
December 24, 2012
On Monday, 24 December 2012 at 18:50:12 UTC, Jonathan M Davis wrote:
> const int& i = foo(bar(min(5, 7)));
>
> which would allow a reference to be kept around, which D disallows.

Does it?

const(int)* i = &foo(bar(min(5, 7)));
December 24, 2012
On Monday, December 24, 2012 20:46:00 anonymous wrote:
> On Monday, 24 December 2012 at 18:50:12 UTC, Jonathan M Davis
> 
> wrote:
> > const int& i = foo(bar(min(5, 7)));
> > 
> > which would allow a reference to be kept around, which D disallows.
> 
> Does it?
> 
> const(int)* i = &foo(bar(min(5, 7)));

That's a pointer, not a ref. It's completely different. It's also @system, whereas ref is @safe.

- Jonathan M Davis