C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Return type deduction

From: Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
Date: Wed, 9 Mar 2022 09:45:27 -0500
There is another alternative; in fact it was how I thought multiple returns
worked for several years, until I recently found out that it was just the
Mandela Effect.
The way I thought they worked was: The *lexically first* return is the one
that counts. Every other return will implicitly convert to the
first-deduced type.

    auto f(int *p) { if (cond) return p; return nullptr; } // Proposed:
OK, return int*
    auto f(int *p) { if (cond) return nullptr; return p; } // Proposed:
Still error, cannot convert int* to deduced return type std::nullptr_t

I personally wouldn't mind if this version was how things really worked.
However, I see that it's arguably confusing and suboptimal, and closes the
door to potentially better alternatives in the future. The current rule —
"every return must *exactly match* the lexically first one" — follows
WG21's general principle of doing the most conservative thing possible in
order to leave these doors open.

I agree with the other repliers that:
- "Take the common_type of all the returns" is too heavyweight for
human brains.
- "Wait to see the last return before you are able to deduce the return
type" is too heavyweight to force the compiler to keep track of.
And I'll add:
- "No recursive calls allowed" is too restrictive.

auto factorial(int n) {
    if (n == 0) return 1; // Today: OK, deduced return type is `int`
    return n * factorial(n-1);
    // How can we type-check this without knowing the type of
`factorial(n-1)`?
    // How can we know the type of `factorial(n-1)` if a `return` ten lines
later in the same function might change the return type?
    ~~~
    return 42L; // ha ha, now your return type is `long`! Hope you didn't
make any decisions based on `int` earlier!
}

–Arthur


On Wed, Mar 9, 2022 at 9:23 AM Lénárd Szolnoki via Std-Proposals <
std-proposals_at_[hidden]> wrote:

> Hi,
>
> So what would the rule be for three return statements? The ternary
> operator rules are only specified for two arguments.
>
> Personally I'm not a fan of introducing some kind of common type here.
>
> Cheers,
> Lénárd
>
>
> ------------------------------
> *From:* Baruch Burstein via Std-Proposals <std-proposals_at_[hidden]>
> *Sent:* March 9, 2022 1:46:36 PM GMT+00:00
> *To:* std-proposals_at_[hidden]
> *Cc:* Baruch Burstein <bmburstein_at_[hidden]>
> *Subject:* [std-proposals] Return type deduction
>
> Hi,
> Under the current rules, if a function uses return-type deduction
> (a.k.a. auto return), all the return statements must deduce to the
> same type. I want to suggest to relax this rule, to match the rules
> for determining the result type of the ternary operator.
> For example, consider these functions:
>
> auto foo(bool b) {
> return b ? 1 : 2.3;
> }
> auto bar(bool b) {
> if (b) return 1;
> return 2.3;
> }
>
> Under the current rules, foo compiles but bar gives an error about the
> return type not matching in all return statements.
>
> I want to suggest that the rule be as follows:
> 1. Deduce all return types of all return statements in the function that:
> a. are not brace-init-lists, and
> b. are not recursive (i.e. don't refer back to this function)
> 2. Deduce return type of function using the same rules as for the ?:
> operator, with appropriate adjustments to account for more than 2
> types (it is a technical adjustment to the wording)
> 3. Once return type has been deduced, allow using the function
> recursively, and allow return statements using brace-init-list as-if
> the return type was explicit in the function declaration.
>
> So, with those rules, all of the following (contrived) examples would be ok:
>
> auto f1(bool b) {
> if (b) return 1;
> return 2.3;
> }
>
> auto f2(bool b) {
> if (b) return {};
> return std::string("hello");
> }
>
> auto f3(bool b) {
> if (b) return f3(false) + " world";
> return std::string("hello");
> }
>
> template <class D>
> auto scope(bool b, D&& del) {
> if (b)
> return std::unique_ptr<void, D>((void*)1, std::forward<D>(del));
> return {};
> }
>
> I would love to hear people's thoughts on this.
> --
> 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 2022-03-09 14:45:39