只有布尔文字值的概念是否格式错误,不需要诊断?
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]
我在一个完全从任何模板中删除的上下文中研究 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 itsInner2
template would result in a valid expression. — end example]