Date: Mon, 12 Jan 2026 10:27:56 +0100
On 12/01/2026 01:00, Frederick Virchanza Gotham via Std-Proposals wrote:
> Consider the following generic line of code:
>
> if ( handle const h = CreateHandle( 0xff ) ) return h;
>
> Right now I'm patching the GNU g++ compiler, inside the file
> "gcc/cp/typeck.cc", inside the function
> "finish_class_member_access_expr" because I want it to return early if
> it's dealing with a chimeric_ptr. However if it's not dealing with a
> chimeric_ptr, I want it to keep going. So right now the line of code
> I'm adding looks like this:
>
> if ( tree const t = check_for_chimera(name, object) ) return t;
>
> To be very generic about what the above line of code is doing:
> (1) It invokes a function (let's call it the callee function).
> (2) If the callee's return value after conversion to bool yields
> true, then the callee's return value is immediately returned from the
> enclosing function.
> (3) If the callee's return value after conversion to bool yields
> false, the enclosing function keeps going.
>
> So to break it down logically, here's what's going on:
>
> auto const retval = SomeFunction();
> if ( static_cast<bool>(retval) ) return retval;
>
> Now personally I think that this would be much more succinctly
> expressed as follows:
>
> return if SomeFunction();
>
> And so if we take another look at the line of code I'm adding to the
> GNU g++ compiler:
>
> if ( tree const t = check_for_chimera(name, object) ) return t;
>
> It could become:
>
> return if check_for_chimera(name, object);
>
> I can think of loads of times over the past 20+ years when I've coded
> a function that does exactly this -- it returns immediately if the
> callee succeeded, or it keeps going if the callee failed. This can be
> simplified with "return if". And you'll see the benefit of it when you
> have multiple function calls:
>
> Symbol *resolve_symbol(Name &name, Scope &scope)
> {
> return if try_fast_path(name, scope);
> return if try_cached(name, scope);
> return if try_builtin_table(name);
>
> // Slow path:
> . . .
> }
>
> This feature is about readability and convenience.
I'm generally in favour of short, clear and convenient code, including
early returns - such as Rust's ? operator for early returns if a Result
(roughly like C++'s std::expect<>) is an error.
However, I /really/ dislike your syntax here, precisely because it is
not at all clear or readable. There are so many different ways this
syntax could reasonably be interpreted when reading it:
return if try_fast_path(name, scope);
Does this mean treat "if try_fast_path(name, scope)" as an expression
and always return its value?
Does it mean "if try_fast_path(name, scope) return;" ?
Does it mean "if try_fast_path(name, scope) return true;" ?
Does it mean "return (bool) try_fast_path(name, scope);" ?
Does it mean "auto t = try_fast_path(name, scope); if (t) return t;" ?
All that possible confusion or reader ambiguity disappears with :
if (auto t = try_fast_path(name, scope)) return t;
It is definitely (IMHO) not worth the significant potential confusion
just to avoid a half dozen characters in the source code.
There is also the issue of the order of actions. C++ is, at heart, an
imperative language - "do this, then do that." Check the condition,
then optionally return. Allowing an "if" statement to be tagged on to
the end of a "return" looks like the start of the slippery slope leading
to Perl...
> Consider the following generic line of code:
>
> if ( handle const h = CreateHandle( 0xff ) ) return h;
>
> Right now I'm patching the GNU g++ compiler, inside the file
> "gcc/cp/typeck.cc", inside the function
> "finish_class_member_access_expr" because I want it to return early if
> it's dealing with a chimeric_ptr. However if it's not dealing with a
> chimeric_ptr, I want it to keep going. So right now the line of code
> I'm adding looks like this:
>
> if ( tree const t = check_for_chimera(name, object) ) return t;
>
> To be very generic about what the above line of code is doing:
> (1) It invokes a function (let's call it the callee function).
> (2) If the callee's return value after conversion to bool yields
> true, then the callee's return value is immediately returned from the
> enclosing function.
> (3) If the callee's return value after conversion to bool yields
> false, the enclosing function keeps going.
>
> So to break it down logically, here's what's going on:
>
> auto const retval = SomeFunction();
> if ( static_cast<bool>(retval) ) return retval;
>
> Now personally I think that this would be much more succinctly
> expressed as follows:
>
> return if SomeFunction();
>
> And so if we take another look at the line of code I'm adding to the
> GNU g++ compiler:
>
> if ( tree const t = check_for_chimera(name, object) ) return t;
>
> It could become:
>
> return if check_for_chimera(name, object);
>
> I can think of loads of times over the past 20+ years when I've coded
> a function that does exactly this -- it returns immediately if the
> callee succeeded, or it keeps going if the callee failed. This can be
> simplified with "return if". And you'll see the benefit of it when you
> have multiple function calls:
>
> Symbol *resolve_symbol(Name &name, Scope &scope)
> {
> return if try_fast_path(name, scope);
> return if try_cached(name, scope);
> return if try_builtin_table(name);
>
> // Slow path:
> . . .
> }
>
> This feature is about readability and convenience.
I'm generally in favour of short, clear and convenient code, including
early returns - such as Rust's ? operator for early returns if a Result
(roughly like C++'s std::expect<>) is an error.
However, I /really/ dislike your syntax here, precisely because it is
not at all clear or readable. There are so many different ways this
syntax could reasonably be interpreted when reading it:
return if try_fast_path(name, scope);
Does this mean treat "if try_fast_path(name, scope)" as an expression
and always return its value?
Does it mean "if try_fast_path(name, scope) return;" ?
Does it mean "if try_fast_path(name, scope) return true;" ?
Does it mean "return (bool) try_fast_path(name, scope);" ?
Does it mean "auto t = try_fast_path(name, scope); if (t) return t;" ?
All that possible confusion or reader ambiguity disappears with :
if (auto t = try_fast_path(name, scope)) return t;
It is definitely (IMHO) not worth the significant potential confusion
just to avoid a half dozen characters in the source code.
There is also the issue of the order of actions. C++ is, at heart, an
imperative language - "do this, then do that." Check the condition,
then optionally return. Allowing an "if" statement to be tagged on to
the end of a "return" looks like the start of the slippery slope leading
to Perl...
Received on 2026-01-12 09:28:06
