如何使用 C++20 概念检查模板本身的一些约束

How to use C++20 concepts to check some constraints in the template itself

抱歉,标题含糊不清,我找不到合适的词来表达它。 我试图强制 class 定义一些 functions/operators 是正确的。例如 ForwardIterator 需要有一些运算符,否则我会得到一个编译器错误。我问了这个问题 ,我得到了一个带有继承的方法,它工作得很好,但 C++20 概念似乎更直观并且给出了更好的错误。 最初的想法是:

template <typename T> concept is_ForwardIterator= requires(T x, T y)
{
    x == y;
};
template <typename T>
requires  is_ForwardIterator<T>
struct ForwardIterator {
};

然后每当我想实现一个前向迭代器时,我继承自 ForwardIterator:

struct MyCustomIterator
   : public ForwardIterator <MyCustomIterator> 
{
  bool operator ==(const MyCustomIterator& other) const;
};

但是编译器一直抱怨MyCustomIterator不满足要求:

error: constraints not satisfied for class template 'ForwardIterator' [with T = MyCustomIterator]
note: because 'MyCustomIterator' does not satisfy 'is_ForwardIterator'
template <typename T> requires is_ForwardIterator<T> struct ForwardIterator {
                               ^
note: because 'x == y' would be invalid: invalid operands to binary expression ('MyCustomIterator' and 'MyCustomIterator')
        x == y;

当您尝试使用 CRTP 时,在基础 class 模板的编译过程中,派生的 class 不完整 。因此,询问有关其行为的大多数问题是不可能的。这包括使用概念的大部分原因。

您尝试做的事情无法以这种方式合理地完成。您可能需要一个特征 class 或其他东西,具体取决于您的目标。

问题在于,在指定 ForwardIterator 约束的地方,class T(即 MyCustomIterator)不完整 - 它作为 class 仅名称。

您需要延迟检查约束,直到 MyCustomIterator 完成。一种方法是 constraint on the destructor of ForwardIterator:

template <typename T>
struct ForwardIterator {
    ~ForwardIterator() requires is_ForwardIterator<T> {}
};

这里唯一的问题是,在有理由实例化析构函数 ~ForwardIterator 之前不会检查它,即如果您实际上没有实例化 MyCustomIterator 对象,则不会检查它.但这在实践中应该不是问题。

在 CRTP 中,导出 class 不完整,因此无法检查其 属性。

使用 traits/concept 检查接口的一种方法是 static_assert 在 class:

之后
template <typename T> concept is_ForwardIterator= requires(T x, T y)
{
    x == y;
    // ...
};

struct MyCustomIterator
{
    bool operator ==(const MyCustomIterator& other) const;
    // ...
};
static_assert(is_ForwardIterator<MyCustomIterator>);