【问题标题】:Can you use constraints on derived classes in CRTP methods?您可以在 CRTP 方法中对派生类使用约束吗?
【发布时间】:2021-05-18 21:32:31
【问题描述】:

类似这样的有效 C++20 代码吗?

#include <iostream>

template <typename T>
concept impls_decrement = requires(T it) { it.decrement(); };

template <class Derived>
struct iterator_facade {
  Derived& operator--()
    requires impls_decrement<Derived>
  {
    auto& self = static_cast<Derived&>(*this);
    self.decrement();
    return self;
  }
};

struct my_iterator : iterator_facade<my_iterator> {
  void decrement() {
    std::cout << "decrement" << std::endl;
  }
};

int main() {
   my_iterator iter;
   --iter;
   return 0;
}

改编自 vector-of-bool 博文。

使用最新版本的 gcc,代码可以工作 fine,但最新版本的 clang 给出了这个 error

prog.cc:25:4: error: cannot decrement value of type 'my_iterator'
   --iter;
   ^ ~~~~
1 error generated.

哪个编译器是正确的?

【问题讨论】:

  • gcc 是正确的。这基本上是clang bug 44833。这就是为 Ranges 指定 view_interface 的方式。
  • Derived 在 CRTP 定义中不完整,但不适用于 CRTP 函数成员实例化。

标签: c++ c++20 crtp


【解决方案1】:

正如 Barry 提到的,代码是有效的,这是 Clang bug 44833

与此同时,我可以通过编写如下代码 (demo) 来解决此问题:

#include <iostream>


template <typename T>
concept impls_decrement = requires(T it) { it.decrement(); };

template <class Derived>
struct iterator_facade {
  template <class T=Derived>
    requires impls_decrement<T>
  Derived& operator--()
  {
    auto& self = static_cast<Derived&>(*this);
    self.decrement();
    return self;
  }
};

struct my_iterator : iterator_facade<my_iterator> {
  void decrement() {
    std::cout << "decrement" << std::endl;
  }
};

int main() {
   my_iterator iter;
   --iter;
   return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-07
    相关资源
    最近更新 更多