C++ Logo

std-proposals

Advanced search

Re: Delay the judgement for coroutine function after the instantiation of template entity.

From: Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
Date: Wed, 20 Jan 2021 09:03:46 -0500
Hi Chuanqi,

I brought this up on the cpplang Slack (in the #coroutines channel).
Personally I tend to agree with your take, but the consensus in Slack
seemed to be "You shouldn't want that."

I'm interested to see your Clang patch. (How short is it?) It might be
interesting to see if you could rework it into a conforming extension (by
adding a diagnostic "ISO C++ forbids coroutines to contain `return`
statements, even in discarded statements") and post it for review.

To solve your actual problem, in C++20, consider using plain old macros,
e.g.

namespace MaybeCoroStuff {
std::conditional_t<USE_CORO, CoroType, ValueType>
func(ValueType v) {
#if USE_CORO
    co_return v;
#else
    return v;
#endif
}
} // namespace MaybeCoroStuff

This still lets you choose between USE_CORO=0 and USE_CORO=1 at compile
time. The downside is that (at least with this naive approach) it lets you
choose only one of these per compilation. If you want to have both the coro
and non-coro versions living side by side in the same program, you'd have
to put this in a header file and do, like,

#define USE_CORO 1
#define MaybeCoroStuff CoroStuff
#include "maybe-coro-stuff.h"
#undef MaybeCoroStuff
#undef USE_CORO

#define USE_CORO 0
#define MaybeCoroStuff NonCoroStuff
#include "maybe-coro-stuff.h"
#undef MaybeCoroStuff
#undef USE_CORO

–Arthur


On Wed, Jan 20, 2021 at 1:48 AM chuanqi.xcq via Std-Proposals <
std-proposals_at_[hidden]> wrote:

> Hi! I am Chuanqi Xu, a new compiler engineer, who is new to this community
> too. Remind me if I do anything wrong.
>
> The following example shows my motivation.
>
> ```
> template<bool UseCoro>
> std::conditional_t<UseCoro, CoroType, ValueType>
> func(ValueType v) {
> if constexpr (UseCoro)
> co_return v;
> else
> return v;
> }
> ```
>
> I want to use constexpr-if grammer to make it possible that programmer
> could choose to use a normal function or a coroutine at compile time.
> However, both gcc and clang emit error for above example because we can't
> use `return` in a coroutine.
>
> Then I find this behavior is desired by the standard.
>
> 8.5.2.2 from N4878 says:
> ```
>
> If the if statement is of the form if constexpr, the value of the
> condition shall be a contextually converted
>
> constant expression of type bool (7.7); this form is called a constexpr
> if statement. If the value of the converted
>
> condition is false, the first substatement is a discarded statement,
> otherwise the second substatement, if
>
> present, is a discarded statement. During the instantiation of an
> enclosing templated entity (13.1), if the
>
> condition is not value-dependent after its instantiation, the discarded
> substatement (if any) is not instantiated.
> ```
>
> and 8.7.5.1 from N4878 says:
> ```
>
> A coroutine returns to its caller or resumer (9.5.4) by the co_return
> statement or when suspended (7.6.2.4).
>
> A coroutine shall not enclose a return statement (8.7.4).
>
> [Note 1 : For this determination, it is irrelevant whether the return
> statement is enclosed by a discarded statement
>
> (8.5.2). —end note]
> ```
>
> I think the Note in 8.7.5.1 is a little bit odd. From my point of view,
> the logic is:
> 1. a function who contains one of `co_*` keywords is a coroutine.
> 2. a template function stands for a family of functions. Only a
> instantiated template function stands for a function.
> 3. From 1 and 2, we should judge whether a template function is a
> coroutine after it is instantiated.
>
> So I am a little bit confusing why there is a note in 8.7.5.1. And I think
> we should remove this constraint if there is no other special reasons.
>
> I did a simple patch in clang which could make the example above to
> compile. So I think the implementation would not be very hard.
>
> The reason why we want this feature is that my collegues find that:
> coroutine get great improvement in some situations while getting big
> regression in other situations.
> As a compiler programmer, I think it is hard to optimize coroutine fast as
> normal function in all cases.
> So I think it would be a solution that programmer could choose to use a
> coroutine function or a normal function at compile time.
>
> Thanks,
> Chuanqi
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>

Received on 2021-01-20 08:04:00