需要带有纯抽象类类型参数的子句?

康桓瑋*_*康桓瑋 13 c++ abstract-class language-lawyer c++-concepts c++20

考虑以下简单concept:

template <typename T>
concept C = requires(T a) { a.f(); };
Run Code Online (Sandbox Code Playgroud)

如果我们将抽象类类型作为requires 表达式的参数会发生什么?

struct B { virtual void f() = 0; };

static_assert(C<B>);
Run Code Online (Sandbox Code Playgroud)

gcc-trunk 和 msvc-trunk通过断言,但是,clang-trunk、gcc-10.2 和 msvc v19.24拒绝该断言。

标准怎么说?

Bri*_*ian 8

GCC-trunk 和 MSVC-trunk 是正确的。由于P0929,抽象类型的使用限制在C++17 和 C++20 之间发生了变化。因此,现在甚至允许带有抽象参数类型的普通函数声明:

void foo(B b);  // ill-formed in C++17, well-formed in C++20
void foo(B b) { /* ... */ }  // still ill-formed in C++20
Run Code Online (Sandbox Code Playgroud)

删除了“抽象类不得用作参数类型...”(C++17 [class.abstract]/3)的措辞。在 C++20 中,只有当函数被调用 ([expr.call]/7) 或定义 ([dcl.fct.def.general]/2 )。此外,在requires-parameter-list 中找到的参数声明不是定义,就像在函数的非定义声明中找到的参数声明不是定义一样 ([basic.def]/2.8)。

  • 这种明显无用的放松的原因是可以使用**不完整**类的参数类型来声明函数;如果将该类后续定义为抽象类,则追溯性地使函数声明无效将会出现问题。 (6认同)