I have inherited the following:
template <typename T>
concept IsAwaiter = requires {
typename T::await_ready;
typename T::await_suspend;
typename T::await_resume;
};
template <typename ...AWAITABLES>
concept IsAwaitables = typename std::conjunction<IsAwaiter<AWAITABLES>...>::type;
Building this with clang 10.0.0 results in the following error:
IsAwaiter.h:43:50: error: template argument for template type parameter must be a type
Perhaps just a simple syntax issue, but I've found it hard to find an example which shows how to create a concept based on a variadic template concept parameter.
Any help appreciated!
std::conjunction
is for type traits. std::conjunction<IsAwaiter<AWAITABLES>...>
is a type with a member static bool value = (IsAwaiter<AWAITABLES>::value && ...)
, where each IsAwaiter<AWAITABLES>
is itself expected to be a type trait with its own static bool
member value
. This is nonsensical when IsAwaiter<AWAITABLES>
is a concept, because concepts are not type traits. They are "just" booleans. Use a fold expression.
template <typename... AWAITABLES>
concept IsAwaitables = (IsAwaiter<AWAITABLES> && ...);
That's it.
struct Dummy {
using await_ready = Dummy;
using await_suspend = Dummy;
using await_resume = Dummy;
};
int main() {
static_assert(IsAwaitables<>);
static_assert(IsAwaitables<Dummy>);
static_assert(IsAwaitables<Dummy, Dummy>);
}
As HTNW points out, you want:
template <typename ...T>
concept IsAwaitables = (IsAwaiter<T> && ...);
But really, do you even need this concept at all? You can just use IsAwaiter
directly. And it probably should just be named Awaiter
- the typical convention for concepts is to name them as nouns rather than questions (e.g. Range
vs IsRange
).
If you're taking a parameter pack, you would want to use it anyway:
template <Awaiter... T>
void f(T... awaiters);
and the same with the abbreviated function template syntax:
void f(Awaiter auto... awaiters);
or if you have a fixed number of them, it especially doesn't make sense:
template <Awaiter T, Awaiter U>
void f(T, U);
And even in other contexts where it doesn't neatly fit, it seems better to just manually use Awaiter
with a fold-expression. So I question the need for the conjunction concept to begin with.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With