只有布尔文字值的概念是否格式错误,不需要诊断?

Are concepts with only a boolean literal value ill-formed, no diagnostic required?

我在一个完全从任何模板中删除的上下文中研究 C++ 概念和函数重载,偶然发现了这个:

struct S
{
    int mult(int x) requires (true)  { return x; }
    int mult(int x) requires (false) { return x * 2; }
};

int main()
{
    std::cout << S{}.mult(5) << std::endl;
}

g++ 11 拒绝编译此代码段,因为 requires-子句可能未附加到非模板函数。

然而,

clang++ 13 对这个代码段来说很好,但令人惊讶的是吐出 10 而不是我预期的 5

我知道C++20标准最近才出炉,所以我完全理解在概念上有很多问题需要解决。

忽略常量文字概念的明显无用性,我的问题是:带有 requires 子句的程序是否总是 false 格式错误,可能不需要诊断? 或者,也许,正如 g++ 所说,我什至根本没有合法的 C++?

您的代码段不是合法的 C++。

[dcl.decl.general]

4 The optional requires-clause ([temp.pre]) in an init-declarator or member-declarator shall be present only if the declarator declares a templated function ([dcl.fct]). When present after a declarator, the requires-clause is called the trailing requires-clause. [...]

由于看不到模板(并且没有讨论 mult 重载是否为模板函数的余地),您的尝试显然是错误的。这是可诊断规则的“应”要求。

所以 GCC 是正确的。 Clang 调用完全不直观的重载是双重错误的。虽然当它接受程序时它真的去了rails。

这些是标准“尾随要求子句”部分中的前两个示例:

void f1(int a) requires true;               // error: non-templated function

template<typename T>
  auto f2(T a) -> bool requires true;       // OK

尽管标准中给出的示例显然是非规范的,但这些示例的意图非常清楚。

本质上,概念只能应用于模板函数(因此您的代码是无效的 C++),但布尔文字(例如,requires true)是完全有效的。

但是,其要求从未得到满足的模板(无论是 required 子句中的文字 false 还是其他方式)似乎格式不正确,如 this example 所示,

正如所说,概念只能与模板一起使用。所以你的例子格式不正确。

如果模板中出现了一个始终为 false 的 requires-clause 怎么办?根据[temp.res.general]/6.1:

The program is ill-formed, no diagnostic required, if:

  • no valid specialization can be generated for a template or a substatement of a constexpr if statement within a template and the template is not instantiated, or ...

它仍然格式错误,但不需要诊断。 [temp.res.general]中的Example 11也证实了这一点。

[Example 11:

template<typename T> struct S1 {
  template<typename U>
    requires false
  struct Inner1;                // ill-formed, no diagnostic required
};

template<typename T> struct S2 {
  template<typename U>
    requires (sizeof(T[-(int)sizeof(T)]) > 1)
  struct Inner2;                // ill-formed, no diagnostic required
};

The class S1<T>​::​Inner1 is ill-formed, no diagnostic required, because it has no valid specializations. S2 is ill-formed, no diagnostic required, since no substitution into the constraints of its Inner2 template would result in a valid expression. — end example]