为什么C++20中需要concept关键字?

M Q*_*ezo 3 c++ language-design c++-concepts c++20

概念很棒,不要误会我的意思,但是为什么我们需要另一个关键字呢?

考虑以下示例:

#include <type_traits>

template <typename T>
concept UnsignedConst = std::is_integral_v<T> && std::is_const_v<T>;

template <UnsignedConst T>
void foo(T bar);
Run Code Online (Sandbox Code Playgroud)

我们也可以使用以下(我认为更直接的)语法:

/* ... */
template <typename T>
constexpr bool UnsignedConst = std::is_integral_v<T> && std::is_const_v<T>;
/* ... */
Run Code Online (Sandbox Code Playgroud)

在幕后,概念只不过是取决于模板参数的编译时布尔常量(编辑:否!请参阅接受的答案)。甚至requires-clauses 也可以与变量模板一起使用,因为它们只是在编译时计算为布尔值的表达式。

Nic*_*las 11

在幕后,概念只不过是取决于模板参数的编译时布尔常量。

这是不真实的。

Aconcept具有constexpr bools 所没有的特殊性质。特别是,aconcept不能被专门化。这种无法专门化的情况使得概念包含规则成为可能。它允许标准为模板的“更专业”版本制定规则。

鉴于以下情况:

template<typename T>
concept A = atomic_constraint_a<T>;

template<typename T>
concept B = atomic_constraint_a<T> && atomic_constraint_b<T>;
Run Code Online (Sandbox Code Playgroud)

A.所包含的C++ 概念规则很清楚B。这意味着任何T满足的类型都B 必然满足A。因此,如果您有两个模板,一个受约束,A另一个B受约束,如果您传递满足 的类型B,那么即使存在 的版本,也会选择该模板A

专业化会破坏这一点,因为有人可能会以不包含 的方式专业化某种B类型。UA<U>B<U>

那么……接下来会发生什么呢?U当有人尝试向上述模板提供竞争约束时会发生什么?主要约束表明存在包含关系,但特殊约束则不存在。

更重要的是,我什至可以编写两个具有包含关系的概念并确保这种关系得到维护吗?也就是说,在一个专业化的世界中,我可以依赖模板接口中的包含吗?

不,使包容成为可能的唯一方法是禁止专业化。但变量模板可以专门化。所以现在你需要一个新的结构来表达“我有点像那个东西,但你不能专门化我”。我们可以让每个人都打字template<typename T> [[nonspecialized]] inline constexpr bool concept_name = X以获得包容(以及概念提供的其他东西)。

或者我们可以直接说template<typename T> concept concept_name = x并消除一堆语法噪音。

此外,concepts 不能是类的成员。这也很重要,因为这意味着您无法通过围绕某个概念专门化类来对该概念进行事实上的专门化。

此外,通过创建一个concept特殊的句法结构,由它自己的语法标记引入,它允许语言更容易地在新的地方使用concepts。例如,std::integral auto var_name = func();。编译器可以看到这std::integral是一个代表概念的标识符。如果它看到一个constexpr bool变量,您可能打算将其用作一个概念。或者您可能打算以其他方式使用它。通过使概念成为一种独特的事物,我们消除了任何歧义。

这使得我们能够在语法中以各种方式使用类型概念,如果没有专门的语法,这将是困难的。也许您可以将属性或某些内容应用于constexpr inline bool,但同样...为什么当您只是想说时使用所有关键字concept