【问题标题】:How to use C++20 concepts to check some constraints in the template itself如何使用 C++20 概念检查模板本身的一些约束
【发布时间】:2020-12-28 17:14:07
【问题描述】:

抱歉标题含糊不清,我找不到合适的词来表达它。 我试图强制一个类定义一些正确的函数/运算符。例如ForwardIterator 需要有一些运算符,否则我应该得到一个编译器错误。我已经问过here 的问题,我得到了一个带有继承的方法,它工作得很好,但是 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;

【问题讨论】:

  • ForwardIterator 的目的是什么?只是一种标记和检查自定义类型以满足约束的方法?如果是这样,如果类型必须选择加入此检查,为什么不能在完整的类定义之后对类型进行静态断言? class MyCustomIterator{}; static_assert(is_ForwardIterator&lt;MyCustomIterator&gt;);
  • 您知道== 重载的参数应该是const 引用参数,而不是可变引用参数吗?
  • 在类的定义中添加约束有点奇怪。通常你会想在使用类时检查约束。

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


【解决方案1】:

当您尝试使用 CRTP 时,在编译基类模板期间,派生类不完整。因此,就其行为提出大多数问题是不可能的。这包括使用概念的大部分原因。

您尝试做的事情不能以这种方式合理地完成。你可能需要一个特质类或其他东西,这取决于你的目标是什么。

【讨论】:

    【解决方案2】:

    问题是在ForwardIterator 的约束被指定的地方,T 类(即MyCustomIterator)是不完整的——它仅作为类名存在。

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

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

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

    【讨论】:

      【解决方案3】:

      在 CRTP 中,派生类不完整,因此无法检查其属性。

      使用特征/概念检查接口的一种方法是在课程之后简单地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>);
      

      【讨论】:

        猜你喜欢
        • 2022-09-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多