将约束应用于模板的三种方式有什么区别?

What is the difference between the three ways of applying constraints to a template?

我刚刚了解到 C++20 提供了三种将约束应用于模板的方法:

我成功地使用了受约束的模板参数,而且我更喜欢这种语法。我仍然想知道为什么标准中定义了 三种 方式。

是否存在根本的技术差异?这些风格是否有独特的优点或缺点(除了语法外观)?

没有技术差异。

// (1)
void foo(Concept auto&& x);

与以下内容完全相同:

// (2)
template <Concept T>
void foo(T&& x);

与以下内容完全相同:

// (3)
template <typename T> requires Concept<T>
void foo(T&& x);

与以下内容完全相同:

// (4)
template <typename T>
void foo(T&& x) requires Concept<T>;

...但只需选择一个并将其一致地用于同一功能(不能用一种语法声明并用另一种语法定义)。

它们中的每一个都有存在的理由 - (1) 比 (2) 短,但 (2) 给你类型的名称 - 然后你可以在其他地方使用。 (2) 比 (3) 和 (4) 更短,但 (3) 和 (4) 更通用并且允许更多种类的约束。 (3) 和 (4) 看起来一样,但是 (4) 是 class 模板的成员函数所必需的,并且还允许您访问参数名称。