c++ 概念如何结合概念?

Bob*_*ker 5 c++ variadic c++-concepts c++20

我继承了以下内容:

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;
Run Code Online (Sandbox Code Playgroud)

使用 clang 10.0.0 构建它会导致以下错误:

IsAwaiter.h:43:50: error: template argument for template type parameter must be a type
Run Code Online (Sandbox Code Playgroud)

也许只是一个简单的语法问题,但我发现很难找到一个示例来展示如何基于可变参数模板概念参数创建概念。

任何帮助表示赞赏!

HTN*_*TNW 8

std::conjunction用于类型特征。std::conjunction<IsAwaiter<AWAITABLES>...>是具有成员的类型static bool value = (IsAwaiter<AWAITABLES>::value && ...),其中每个IsAwaiter<AWAITABLES>本身都应该是具有自己static bool成员的类型特征value。当IsAwaiter<AWAITABLES>是一个概念时,这是荒谬的,因为概念不是类型特征。它们“只是”布尔值。使用折叠表达式。

template <typename... AWAITABLES>
concept IsAwaitables = (IsAwaiter<AWAITABLES> && ...);
Run Code Online (Sandbox Code Playgroud)

就是这样。

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>);
}
Run Code Online (Sandbox Code Playgroud)


Bar*_*rry 6

正如HTNW 指出的,你想要:

template <typename ...T>
concept IsAwaitables =  (IsAwaiter<T> && ...);
Run Code Online (Sandbox Code Playgroud)

但真的,你甚至需要这个概念吗?IsAwaiter直接使用就可以了。它可能应该只是命名Awaiter- 概念的典型约定是将它们命名为名词而不是问题(例如Rangevs IsRange)。

如果您正在使用参数包,您无论如何都想使用它:

template <Awaiter... T>
void f(T... awaiters);
Run Code Online (Sandbox Code Playgroud)

与缩写的函数模板语法相同:

void f(Awaiter auto... awaiters);
Run Code Online (Sandbox Code Playgroud)

或者如果你有固定数量的它们,那尤其没有意义:

template <Awaiter T, Awaiter U>
void f(T, U);
Run Code Online (Sandbox Code Playgroud)

即使在它不完全适合的其他上下文中,手动使用Awaiter折叠表达式似乎更好。所以我质疑连词概念的必要性。