C++ Logo

std-proposals

Advanced search

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

From: Omry Noam <omrynoam_at_[hidden]>
Date: Wed, 20 Jan 2021 16:21:12 +0200
What if we specialized a function template templated on bool, to have one
version that's a coroutine, and one version that's a normal function?

Maybe something like: https://godbolt.org/z/7TEnb6
(Code adapted from cppreference as an example)

On Wed, Jan 20, 2021 at 4:04 PM Arthur O'Dwyer via Std-Proposals <
std-proposals_at_[hidden]> wrote:

> 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
>>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>

Received on 2021-01-20 08:21:28