只有布尔文字值的概念是格式错误的,不需要诊断吗?
我在完全从任何模板中删除的上下文中玩弄 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-clauses 可能不会附加到非模板函数。
然而,clang++ 13 对这个代码段很好,但令人惊讶的是它吐出10而不是5我所期望的。
我知道 C++20 标准最近才出炉,所以我完全理解关于概念有很多问题需要解决。
忽略常量字面概念的明显无用,我的问题是:带有 -requires子句的程序是否总是格式错误的false,可能不需要诊断?或者,也许,正如 g++ 所说,我什至根本没有合法的 C++?
回答
您的代码段不是合法的 C++。
[dcl.decl.general]
4 init-declarator 或member-declarator 中的可选requires-clause ([temp.pre]) 仅在声明器声明模板化函数([dcl.fct]) 时才出现。当出现在声明符之后时,requires-clause 被称为尾部 requires-clause。[...]
由于看不到模板(并且没有讨论mult重载是否是模板化函数的余地),因此您的尝试显然是格式错误的。这是可诊断规则的“应该”要求。
所以GCC是正确的。Clang 调用完全不直观的重载是双重错误的。尽管当它接受该计划时它确实出轨了。
- @CoffeeTime - 我不明白为什么预处理时间会很糟糕,但我可能不明白你在做什么。它可能是另一个问答的主题。
回答
这些是标准的“尾随要求条款”部分中的前两个示例:
void f1(int a) requires true; // error: non-templated function
template<typename T>
auto f2(T a) -> bool requires true; // OK
尽管标准中给出的示例显然是非规范性的,但这些示例使意图非常明确。
本质上,概念只能应用于模板函数(因此您的代码是无效的 C++),但布尔文字(例如,requires true)是完全有效的。
但是,其要求从未得到满足(无论false是required子句中的文字还是其他方式)的模板似乎格式错误,如本示例所示,