Thread overview | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
June 22, 2015 auto ref is on the docket | ||||
---|---|---|---|---|
| ||||
Walter and I discussed what auto ref for templates should look like and reached the conclusion that an approach based on lowering would be best. I added a proposed lowering to https://github.com/D-Programming-Language/dmd/pull/4717. Andrei |
June 22, 2015 Re: auto ref is on the docket | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | On 6/22/15 12:11 AM, Andrei Alexandrescu wrote:
> Walter and I discussed what auto ref for templates
You mean *non-templates*? auto ref for templates has a very well defined meaning.
And reading your post, I'm unclear what exactly happens. Does this generate 2 functions from one, and then call the wrapper for auto-ref?
So for instance:
ref int fun(auto ref int x);
What happens here?
auto x = &fun;
x(5);
-Steve
|
June 22, 2015 Re: auto ref is on the docket | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On 6/21/2015 10:08 PM, Steven Schveighoffer wrote:
> On 6/22/15 12:11 AM, Andrei Alexandrescu wrote:
>> Walter and I discussed what auto ref for templates
>
> You mean *non-templates*? auto ref for templates has a very well defined meaning.
>
> And reading your post, I'm unclear what exactly happens. Does this generate 2
> functions from one, and then call the wrapper for auto-ref?
>
> So for instance:
>
> ref int fun(auto ref int x);
>
> What happens here?
>
> auto x = &fun;
> x(5);
>
> -Steve
>
The idea is that fun(5) would be lowered to:
auto tmp = 5;
fun(tmp);
But when talking to Andrei I didn't realize that it would be subtly different behavior than 'auto ref' for template functions, which makes me concerned that this is not a good idea.
Note that one can always rewrite:
ref int fun(ref int x);
into:
ref int fun()(auto ref int x);
if auto ref is desired.
|
June 22, 2015 Re: auto ref is on the docket | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On Monday, 22 June 2015 at 05:25:57 UTC, Walter Bright wrote:
> On 6/21/2015 10:08 PM, Steven Schveighoffer wrote:
>> On 6/22/15 12:11 AM, Andrei Alexandrescu wrote:
>>> Walter and I discussed what auto ref for templates
>>
>> You mean *non-templates*? auto ref for templates has a very well defined meaning.
>>
>> And reading your post, I'm unclear what exactly happens. Does this generate 2
>> functions from one, and then call the wrapper for auto-ref?
>>
>> So for instance:
>>
>> ref int fun(auto ref int x);
>>
>> What happens here?
>>
>> auto x = &fun;
>> x(5);
>>
>> -Steve
>>
>
> The idea is that fun(5) would be lowered to:
>
> auto tmp = 5;
> fun(tmp);
>
> But when talking to Andrei I didn't realize that it would be subtly different behavior than 'auto ref' for template functions, which makes me concerned that this is not a good idea.
>
> Note that one can always rewrite:
>
> ref int fun(ref int x);
>
> into:
>
> ref int fun()(auto ref int x);
>
> if auto ref is desired.
I think too that it's unclear and misleading. What will happen if auto ref function will be templated? How it interacts with xurrent logic ?
And why not simply allow "ref in" to pass a temporary object?
|
June 22, 2015 Re: auto ref is on the docket | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | On Monday, 22 June 2015 at 04:11:41 UTC, Andrei Alexandrescu wrote:
> Walter and I discussed what auto ref for templates should look like and reached the conclusion that an approach based on lowering would be best. I added a proposed lowering to https://github.com/D-Programming-Language/dmd/pull/4717.
So, you're basically suggesting that have an auto ref parameter on a non-templated function basically does the combinatorial explosion of function definitions that you get with templated functions except that all of the combinations are instantiated (the one difference then being that all of the overloads except the one with all refs would just be wrappers calling the one with all refs)? That doesn't sound particularly desirable me. It's better than writing all of those wrappers by hand, but that's still likely to be a fair bit of code bloat if you're using auto ref parameters much - and if the folks coming from C++ who have been begging for this get it, they _will_ start using it all over the place.
I would have thought that we'd define this such that the compiler introduced a variable restricted to the scope of the statement for each rvalue passed as an auto ref parameter rather than introducing function overloads. No, that's not quite as nice a lowering, but it would avoid a lot of extraneous function definitions.
- Jonathan M Davis
|
June 22, 2015 Re: auto ref is on the docket | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On Monday, 22 June 2015 at 05:25:57 UTC, Walter Bright wrote: > The idea is that fun(5) would be lowered to: > > auto tmp = 5; > fun(tmp); That's not what Andrei described (though it's what I would have expected us to do). Rather, Andrei seems to be suggesting that having an auto ref parameter would result in defining both a ref and non-ref overload of the function (with the non-ref one forwarding to the ref one), which would unfortunately result in a combinatorial explosion of function definitions (just like the templated version does, except that all of the overloads would just forward to the one which took all refs, and all of the overloads would always exist regardless of whether they were called). So, I'm inclined to think that what you just suggested makes a lot more sense than what Andrei suggested. > But when talking to Andrei I didn't realize that it would be subtly different behavior than 'auto ref' for template functions, which makes me concerned that this is not a good idea. I don't see how there's any way around that given that the behavior of the templated auto ref pretty much depends on the function being templated, though Andrei's suggestion comes a lot closer than having the compiler insert a variable for you. Also, by reusing auto ref for this rather than coming up with a new attribute, we can't declare templated functions with the same behavior as the non-templated ones would get for auto ref (though that's a lot more important IMHO if we implement it via introducing a variable rather than introducing overloads, since then we'd be able to avoid the template bloat in the cases where you're just trying to accept both lvalues and rvalues and don't care about forwarding refness). > Note that one can always rewrite: > > ref int fun(ref int x); > > into: > > ref int fun()(auto ref int x); > > if auto ref is desired. Yes, but to be honest, the way that Andrei is suggesting that we implement this is so close to just templatizing the function that the only benefit to it I see over the status quo is that it would work with virtual functions, whereas the templated version obviously won't. I really think that we should consider implementing this via _one_ function where all of the auto ref parameters are lowered to ref, and variables are added where necessary by the compiler rather than implementing it via lowering it to a combinatorial explosion of overloads. And if we _do_ implement this via a single function with the compiler adding variables rather than having the compiler add overloads, I really think that we should consider introducing a new attribute for this so that we can use it with templated functions and avoid all of the template bloat that we get with auto ref right now. There are cases where auto ref is exactly what you want, but there are plenty of cases where folks use it just so that they can have their function accept both lvalues and rvalues, and in that case, all of the extra template instantiations are just bloat. So, if we had @anyref or whatever we wanted to call it, we could use it both with templated and non-templated functions, and we would avoid the confusion introduced by having auto ref mean different things for templated and non-templated functions. Yes, that would mean introducing another attribute, which kind of sucks, but its use is specific enough that I think that it would be worth having, and I fully expect that it would be a big help in reducing template bloat in many programs - especially from those folks who keep clamoring for C++'s const& in D. - Jonathan M Davis |
June 22, 2015 Re: auto ref is on the docket | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On 6/21/15 10:08 PM, Steven Schveighoffer wrote: > On 6/22/15 12:11 AM, Andrei Alexandrescu wrote: >> Walter and I discussed what auto ref for templates > > You mean *non-templates*? auto ref for templates has a very well defined > meaning. Yes, non-tempaltes. > And reading your post, I'm unclear what exactly happens. Does this > generate 2 functions from one, and then call the wrapper for auto-ref? > > So for instance: > > ref int fun(auto ref int x); > > What happens here? > > auto x = &fun; > x(5); What you'd expect after lowering: error. Andrei |
June 22, 2015 Re: auto ref is on the docket | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On 6/21/15 10:25 PM, Walter Bright wrote: > On 6/21/2015 10:08 PM, Steven Schveighoffer wrote: >> On 6/22/15 12:11 AM, Andrei Alexandrescu wrote: >>> Walter and I discussed what auto ref for templates >> >> You mean *non-templates*? auto ref for templates has a very well >> defined meaning. >> >> And reading your post, I'm unclear what exactly happens. Does this >> generate 2 >> functions from one, and then call the wrapper for auto-ref? >> >> So for instance: >> >> ref int fun(auto ref int x); >> >> What happens here? >> >> auto x = &fun; >> x(5); >> >> -Steve >> > > The idea is that fun(5) would be lowered to: > > auto tmp = 5; > fun(tmp); I don't think that lowering is recommended - it prolongs the lifetime of the temporary through the end of the caller. But that may be actually a good thing. > But when talking to Andrei I didn't realize that it would be subtly > different behavior than 'auto ref' for template functions, which makes > me concerned that this is not a good idea. That's fine. > Note that one can always rewrite: > > ref int fun(ref int x); > > into: > > ref int fun()(auto ref int x); > > if auto ref is desired. I don't understand this. My lowering scheme doesn't allow for that. Andrei |
June 22, 2015 Re: auto ref is on the docket | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | On 6/21/15 11:11 PM, Jonathan M Davis wrote:
> No, that's not quite as nice a lowering, but it would avoid a lot of
> extraneous function definitions.
I think a lowering is a must. Matters are complicated as they are, I don't want to add new rules.
Combinatorial issues can be addressed by either generating the functions on demand, or by lowering at the client side.
Andrei
|
June 22, 2015 Re: auto ref is on the docket | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | On 6/21/15 11:31 PM, Andrei Alexandrescu wrote:
> On 6/21/15 10:25 PM, Walter Bright wrote:
>> The idea is that fun(5) would be lowered to:
>>
>> auto tmp = 5;
>> fun(tmp);
>
> I don't think that lowering is recommended - it prolongs the lifetime of
> the temporary through the end of the caller. But that may be actually a
> good thing.
On second thought - Walter's lowering, which makes the rvalue last more than strictly necessary, may be the most flexible of all at the cost of more resource consumption (for types that define destructors). -- Andrei
|
Copyright © 1999-2021 by the D Language Foundation