简体   繁体   English

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

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

Sorry for the ambiguous title, I couldn't find the right words to phrase it.抱歉标题模棱两可,我找不到合适的词来表达它。 I'm trying to force a class to define some functions/operators to be correct.我试图强制 class 将某些函数/运算符定义为正确的。 for example ForwardIterator is required to have some operators otherwise I should get a compiler error.例如ForwardIterator需要有一些运算符,否则我应该得到一个编译器错误。 I have asked the question here and I was given a method with inheritance, it works perfectly but C++20 concepts seem to be more intuitive and give better errors.我在这里问过这个问题,我得到了一个 inheritance 的方法,它工作得很好,但是 C++20 的概念似乎更直观并且给出了更好的错误。 The initial idea is:最初的想法是:

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

Then whenever I want to implement a forward iterator I inherit from ForwardIterator :然后,每当我想实现一个前向迭代器时,我都会从ForwardIterator继承:

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

But the compiler keeps complaining that MyCustomIterator doesn't satisfy the requirement:但是编译器一直抱怨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;

When you try to use the CRTP, during the compilation of the base class template, the derived class is incomplete .当您尝试使用 CRTP 时,在基础 class 模板的编译过程中,派生的 class 是不完整的。 As such, asking most questions about its behavior is impossible.因此,就其行为提出大多数问题是不可能的。 This includes most of the reasons to use a concept.这包括使用概念的大部分原因。

What you're trying to do cannot reasonably be done that way.你试图做的事情不能以这种方式合理地完成。 You may need a traits class or something, depending on what your goal is.您可能需要一个特征 class 或其他东西,这取决于您的目标是什么。

The problem is that where the constraint on ForwardIterator is specified, the class T (that is, MyCustomIterator ) is incomplete - it exists as a class name only.问题是在指定ForwardIterator约束的地方, class T (即MyCustomIterator )不完整 - 它仅作为 class 名称存在。

You need to delay checking of the constraint until after MyCustomIterator is complete.您需要延迟检查约束,直到MyCustomIterator完成。 One way to do this is a constraint on the destructor of ForwardIterator :一种方法是限制ForwardIterator析构函数

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

The only problem here is that this will not be checked until there is a reason to instantiate the destructor ~ForwardIterator , ie if you do not actually instantiate a MyCustomIterator object it will not be checked.这里唯一的问题是,在有理由实例化析构函数~ForwardIterator之前,不会对其进行检查,即如果您没有实际实例化MyCustomIterator object,则不会对其进行检查。 But this should not be a problem in practice.但这在实践中应该不是问题。

In CRTP, derived class in incomplete, so checking its property is not possible.在 CRTP 中,导出 class 不完整,因此无法检查其属性。

One way to check interface with traits/concept is simply static_assert after the class:检查具有特征/概念的接口的一种方法是在 class 之后简单地使用static_assert

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM