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

时间:2020-09-08 18:26:23

标签: c++ c++20 variadic c++-concepts

我继承了以下内容:

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;

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

IsAwaiter.h:43:50: error: template argument for template type parameter must be a type

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

任何帮助表示赞赏!

2 个答案:

答案 0 :(得分:7)

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> && ...);

就是这样。

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>);
}

答案 1 :(得分:5)

作为HTNW points out,您需要:

template <typename ...T>
concept IsAwaitables =  (IsAwaiter<T> && ...);

但是,实际上,您是否甚至需要这个概念?您可以直接使用IsAwaiter。大概应该将其命名为Awaiter-概念的典型约定是将它们命名为名词而不是问题(例如RangeIsRange)。

如果要使用参数包,则还是要使用它:

template <Awaiter... T>
void f(T... awaiters);

与缩写功能模板语法相同:

void f(Awaiter auto... awaiters);

或者如果您有固定的数量,则这毫无意义:

template <Awaiter T, Awaiter U>
void f(T, U);

即使在不合适的其他情况下,最好还是手动使用Awaiter和fold-expression。因此,我对连词概念的开头提出了疑问。