C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Automatic perfect forwarding is possible and not too complicated

From: Frederick Virchanza Gotham <cauldwell.thomas_at_[hidden]>
Date: Thu, 10 Apr 2025 13:58:36 +0100
On Thu, Apr 10, 2025 at 12:20 PM Giuseppe D'Angelo wrote:
>
> template <std::range T>
> void f(T &&& arg)
> {
> auto b = ranges::begin(arg);
> auto e = ranges::end(arg);
>
> use(b, e);
>
> assert(check(arg));
> }


If NDEBUG is defined, the above code becomes:

 template <std::range T>
 void f(T &&arg)
 {
    auto b = ranges::begin(arg);
    auto e = ranges::end( forward<T>(arg) );

    use( b, e );

    (void)0;
 }

Otherwise it becomes:

 template <std::range T>
 void f(T &&arg)
 {
    auto b = ranges::begin(arg);
    auto e = ranges::end(arg);

    use( b, e );

    check( forward<T>(arg) ) || __assert_failure( "check(arg)");
 }

So when compiling in Debug mode, you'll occasionally get an
L-value-accepting function being called instead of an
R-value-excepting function. This isn't a big deal.

I think this is preferable to writing your function as follows:

 template <std::range T>
 void f(T &&arg)
 {
    auto b = ranges::begin(arg);

#ifdef NDEBUG
    auto e = ranges::end( forward<T>(arg) );
#else
    auto e = ranges::end(arg);
#endif

    use(b, e);

    assert(check(arg));
 }

Perhaps in this situation you would even write a macro:

#ifdef NDEBUG
# define FORWARD_IN_RELEASE_MODE(x) (std::forward<decltype(x)>(x))
#else
# define FORWARD_IN_RELEASE_MODE(x) (x)
#endif

And use it as follows:

 template <std::range T>
 void f(T &&arg)
 {
    auto b = ranges::begin(arg);
    auto e = ranges::end( FORWARD_IN_RELEASE_MODE(arg) );

    use(b, e);

    assert( check(arg) );
 }

It would be handier and less prone-to-introducing-bugs to use an
autoforward reference as follows:

 template <std::range T>
 void f(T &&&arg) // trigraph &&& for auto-forwarding
 {
    auto b = ranges::begin(arg);
    auto e = ranges::end(arg); // This will be forwarded if NDEBUG is defined

    use(b, e);

    assert(check(arg));
 }

Received on 2025-04-10 12:58:49