C++ Logo

std-proposals

Advanced search

Re: Operator for reference casting

From: Jean-Baptiste Vallon Hoarau <jeanbaptiste.vallon_at_[hidden]>
Date: Sun, 17 Jan 2021 14:01:16 +0100
Jason :

I suppose you propose to automatically forward the variable at the last use
and not before?

This is equivalent to the (pretty exciting) idea of Herb Sutter for new
kind of functions parameters (in/out/inout/move/forward), see this talk
<https://www.youtube.com/watch?v=6lurOCdaj0Y>

Le dim. 17 janv. 2021 à 10:27, Drew Gross via Std-Proposals <
std-proposals_at_[hidden]> a écrit :

> Some examples of when you don't want to forward a forwarding reference,
> might be easy to create bugs if it forwarded automatically:
>
> 1) A generic logging wrapper function
> ```
> auto LoggedCall(auto >&& f, auto >&& v) {
> LogValue(v);
> return f(v); // Oops, v was moved from! (Maybe, depending on signature
> of LogValue)
> }
> ```
> 2) A generic concatenate function
> ```
> auto Concatenate(auto >&& c1, auto >&& c2) {
> std::vector<decltype(c1)::value_type> result;
> using std::size;
> result.reserve(size(c1) + size(c2)); // Oops! c1 and c2 were moved
> from (OK only if size's signature is weird for c1/c2's type, but you get
> the point)
> // ... add c1 and c2 to result ...
> return result;
> }
> ```
>
>
>
> On Sat, Jan 16, 2021 at 9:14 PM Jason McKesson via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
>
>> On Sat, Jan 16, 2021 at 4:34 PM Bengt Gustafsson via Std-Proposals
>> <std-proposals_at_[hidden]> wrote:
>> >
>> >
>> > >> Given that a language feature has more wiggle room we could define
>> two
>> > >> different operators with limitations in applicability that can't be
>> > >> enforced for a library feature such as std::forward / std::move.
>> > >>
>> > >> prefix -> is a forwarding operator which can only be applied to
>> > >> universal references, i.e. parameters declared with deduced template
>> > >> type and a && modifier.
>> > > And what of `auto &&t = expr;`? In terms of the rules for how `t` gets
>> > > deduced, it is just as much a forwarding reference as a parameter. And
>> > > it's just as reasonable to want to forward `t` as you would for any
>> > > parameter. And yet, the standard's definition of "is a forwarding
>> > > reference" would not include `t`.
>> > Practially you would want it to be possible to forward t here, and
>> > auto&& is a shortcut for the full template syntax. So yes, it should be
>> > included, in contrast with MyType&& x where you would use move (as you
>> > know it is a movable variable).
>>
>> I've been thinking about this for the last few hours, and something
>> occurred to me:
>>
>> We're kinda doing this backwards.
>>
>> We're looking at `std::forward` as being this large, difficult-to-type
>> and not very easy to use wart in our code. And we want to make a
>> shorter version of it. But maybe the problem is not at the point of
>> use.
>>
>> Maybe the problem is that a "forwarding reference" is not a special
>> construct when it *should be*. After all, if a forwarding reference is
>> a special construct, then anytime you use it, we could say that the
>> compiler will *automatically* forward from it. And so we no longer
>> need to apply *any* syntax at the point of use.
>>
>> So how do we do that? A forwarding reference parameter only gains
>> special forwarding reference status if it's declared like this:
>>
>> ```
>> template<typename T>
>> void func(T &&t);
>> ```
>>
>> But we now have a shorthand for that:
>>
>> ```
>> void func(auto &&t);
>> ```
>>
>> So what if we create a syntax specifically for forwarding references?
>> Just as a strawman syntax, we'll use this:
>>
>> ```
>> void func(auto >&&t);
>> ```
>>
>> There would be no long-form version of this with a template header; to
>> create an auto-forwarding-reference, you *must* use `auto`. And you
>> can't slip a cv-qualifier in there either.
>>
>> In terms of the function declaration, it's the same as the above.
>> However, every use of `t` within the function should *automatically*
>> do the forwarding gymnastics. No syntax is needed at the point of use
>> to forward the expression's value category.
>>
>> I feel like this is important because I'm really unsure of when I
>> *wouldn't* want to forward a usage of a forwarding parameter. And if
>> there's a time for that, we can always have a `std::lvalue` function
>> or something for it (if you want an rvalue, you'd use `std::move`).
>>
>> This would work with any usage of `auto` (except maybe in template
>> parameters, but probably there too?):
>>
>> ```
>> auto >&&varname = expr;
>> auto >&&[x, y] = expr;
>> ```
>>
>> `varname` is an automatic forwarding reference, so all uses of
>> `varname` will forward it properly. Uses of `x` and `y` will properly
>> forward from the hidden variable. If the hidden variable is a struct
>> or array, `x` and `y` will carry the value category of the referenced
>> expression as appropriate. Otherwise, it'll return what `get` says to
>> return for the value category of the expression.
>>
>> This cleans up a bunch of code at the point of use of forwarding
>> references, thus making them that much easier to use.
>>
>> > >
>> > > I don't think it's reasonable to have language be functional or
>> > > non-functional based on nebulous properties like "is a forwarding
>> > > reference".
>> >
>> > I don't understand this, do you mean functional as in "working" or
>> > functional as in "pure functional programming"?
>>
>> I meant "working".
>> --
>> Std-Proposals mailing list
>> Std-Proposals_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>

Received on 2021-01-17 07:01:29