if (not m.try_emplace(std::move(s), i).second)
std::format_to(std::ostreambuf_iterator<char>(std::clog),
"failed to insert {}:{}\n", s, i);
// ^
// not use-after-move, by construction

On Thu, 22 Jun 2023 at 14:30, Frederick Virchanza Gotham via Std-Proposals <std-proposals@lists.isocpp.org> wrote:
There's talk lately about a few different proposals to alleviate the
need for 'move' and 'forward'. This kinda indicates that people are
getting a little fed up with all the moving and forwarding -- or at
least fed up with the syntax.

But anyway, without regard to any of those proposals, just as
something totally separate, I want to propose the following:

Make it compulsory for a compiler to issue a diagnostic (and possibly
also terminate compilation) in the following scenario:

    void Func(SomeClass &&obj)
    {
        SomeOtherFunc( move(obj) );

        AndAgainSomeOtherFunction( move(obj) );
    }

So if an object is moved or forwarded more than once inside the body
of a function, the compiler must tell you:

    <source>: In function 'void Func(SomeClass &&obj)':
       warning: R-value possibly moved more than once
    <source>:3:20 first possible move
       20 |    SomeOtherFunc( move(obj) );
    <source>:5:6: second possible move
       32 |    AndAgainSomeOtherFunction( move(obj) );

I use the word 'possible' in the diagnostic message because you could
have code like:

    void Func(SomeClass &&obj)
    {
        if ( some_global_boolean ) SomeOtherFunc( move(obj) );

        AndAgainSomeOtherFunction( move(obj) );
    }

If we were to have this new language feature, it would somewhat
alleviate the possibility of introducing double-move bugs (as Arthur
mentioned yesterday).

If we were to mandate that the compiler must also terminate
compilation, then maybe we should introduce a new way of overriding
this feature, perhaps something like:

    void Func(SomeClass &&obj)
    {
        SomeOtherFunc( std::move(obj) );

        AndAgainSomeOtherFunction( std::override_multi_move(obj) );
    }

or if we want it to also work when casting to "T&&", then we could
make it a core language feature as follows:

    void Func(SomeClass &&obj)
    {
        SomeOtherFunc( (SomeClass&&)obj );

        AndAgainSomeOtherFunction( (override SomeClass&&)obj );
    }

This feature I'm proposing would be useful for the C++ language as it
is today in 2023, even if the language weren't to change. But it will
be even more useful if a future proposal is accepted to do away with
the need for 'move' and 'forward'.
--
Std-Proposals mailing list
Std-Proposals@lists.isocpp.org
https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals