C++ Logo

std-proposals

Advanced search

[std-proposals] Rvalue Parameter : Implicit move and forward

From: Frederick Virchanza Gotham <cauldwell.thomas_at_[hidden]>
Date: Wed, 21 Dec 2022 06:45:34 +0000
It surprises me that reference collapsing made it into the C++
Standard back in 2011.

One of the obvious complications of reference collapsing is that I
can't use simple syntax to write a template function that only accepts
Rvalue arguments, instead I need to use a constraint as on Line #05 :

01: template<typename T>
02: optional<T> stored_object;
03:
04: template<typename T>
05: requires is_rvalue_reference_v<T&&>
06: void store(T &&arg)
07: {
08: stored_object< remove_cvref_t<T> >.emplace( move(arg) );
09: }

Also note on Line #08 that I must use 'move' even though the function
parameter is an Rvalue reference. I started a thread recently on
comp.lang.c++ in which I shared my idea for a different way in which
perfect forwarding could have been implemented:

        https://groups.google.com/g/comp.lang.c++/c/3QhGCWcZfIo

Since the C++11 standard is already written and finished though, I can
only make proposals that won't break existing code. So anyway here's
what my idea is:

In the definition of a function, and not in any declaration of a
function, you may specify the '^' symbol before the name of a function
parameter in order to get implicit use of 'move' and 'forward'. For
example let's declare a function as follows:

    void RecordString(string &&arg);

And now let's define it, and notice that I've put a '^' before the
parameter name:

    void RecordString(string &&^arg)
    {
        some_global_string = arg;
    }

The above function definition is exactly equivalent to:

    void RecordString(string &&arg)
    {
        some_global_string = move(arg);
    }

Now let's take an example using a template function that uses
reference collapsing and 'std::forward' to accept either an Lvalue or
an Rvalue:

    template<typename T>
    void store(T &&arg)
    {
        stored_object< remove_cvref_t<T> >.emplace( forward<T>(arg) );
    }

I propose that the use of 'forward' could be made implicit by applying
'^' to the function parameter:

    template<typename T>
    void store(T &&^arg)
    {
        stored_object< remove_cvref_t<T> >.emplace(arg);
    }

So essentially what the '^' token does here is that if the parameter
is an Rvalue reference, then the argument is treated as an Rvalue
within the body of the function. This goes against the rule of "All
function arguments are Lvalues" but that rule should have been amended
anyway back in 2011.

The '^' token could also be used in range-based 'for' loops:

    for ( auto ^e : some_container ) DoSomethingWithContainerElement(e);

Received on 2022-12-21 06:45:46