[英]Compiler variance for trailing requires-clauses on non-templated functions
Consider the following example:考虑以下示例:
void f() requires true { }
int main() { f(); }
Clang (1) ( DEMO ) accepts this program, whereas GCC (1) ( DEMO ) rejects it with the following error: Clang (1) ( DEMO ) 接受这个程序,而 GCC (1) ( DEMO ) 拒绝它并出现以下错误:
error: constraints on a non-templated function
Note that the constraint expression can actually be used in Clang's case, as the following program is rejected by Clang:请注意,约束表达式实际上可以在 Clang 的情况下使用,因为以下程序被 Clang 拒绝:
void f() requires false { }
int main() { f(); } // // error: no matching function for call to 'f'
with Clang noting that that the declared f
is not a candidate as the constraints were not satisfied (for it to be a candidate for the f()
call; DEMO ). Clang 注意到声明的f
不是候选者,因为不满足约束(因为它是f()
调用的候选者; DEMO )。
(1) GCC HEAD 11.0.0 20210124 and Clang HEAD 12.0.0 (20210124), -std=c++20
. (1) GCC HEAD 11.0.0 20210124 和 Clang HEAD 12.0.0 (20210124),-std -std=c++20
。
All standard references below refer, unless noted otherwise, to N4861 (March 2020 post-Prague working draft/C++20 DIS) .除非另有说明,否则以下所有标准参考均指N4861(2020 年 3 月布拉格后工作草案/C++20 DIS) 。
This is a Clang bug, and GCC is correct to reject the program, as per [dcl.decl]/4 (as well as [temp.constr.decl]/1 ) [ emphasis mine]:这是一个 Clang 错误,并且 GCC 根据[dcl.decl]/4 (以及[temp.constr.decl]/1 )拒绝该程序是正确的[强调我的]:
The optional requires-clause in an init-declarator or member-declarator shall be present only if the declarator declares a templated function ([dcl.fct]).仅当声明符声明模板化 function ([dcl.fct]) 时, init-declarator或成员声明符中的可选requires 子句才应存在。 When present after a declarator, the requires-clause is called the trailing requires-clause .当出现在声明符之后时, requires-clause称为尾随 requires-clause 。 [...] [...]
The same paragraph also contains a (non-normative) example explicitly pointing out the OP's example as ill-formed:同一段落还包含一个(非规范性)示例,明确指出 OP 的示例格式错误:
[ Example: [示例:
void f1(int a) requires true; // error: non-templated function template<typename T> auto f2(T a) -> bool requires true; // OK //...
— end example ] —结束示例]
We may note that in an earlier version of the (to become C++20) working draft, N4810 , [dcl.decl]/4 had a weaker requirement for where requires-clauses were allowed to appear:我们可能会注意到,在(成为 C++20)工作草案的早期版本中, N4810 ,[dcl.decl]/4 对允许出现 requires 子句的位置的要求较弱:
The optional requires-clause (Clause 13) in an init-declarator or member-declarator shall not be present when the declarator does not declare a function (9.2.3.5).当声明符未声明 function (9.2.3.5) 时, init-declarator或member-declarator中的可选requires-clause (第 13 条)不应出现。 [...] [...]
[ Example: [示例:
void f1(int a) requires true; // OK //...
— end example ] —结束示例]
where the non-normative example of the use case of the OP was explicitly shown as well-formed.其中 OP 用例的非规范示例被明确显示为格式正确。 The original intent there was arguably to allow constraining of non-template member functions of class templates based on the template parameters of the class template:可以说,最初的意图是允许基于 class 模板的模板参数来约束 class 模板的非模板成员函数:
#include <iostream>
template<bool B>
struct S {
void f() requires B { std::cout << "true\n"; }
void f() requires (!B) { std::cout << "false\n"; }
};
int main() {
S<true>{}.f(); // true
S<false>{}.f(); // false
}
this is still allowed in the final state (intended for C++20) of [dcl.decl]/4 in N4861, where the restriction is to that of a templated function (see templated entity in [temp.pre]/8 , particularly [temp.pre]/8.3 ), which does not only cover function templates (and function template members of non-templates and template class templates), but also non-template member functions of class templates.这在 N4861 中 [dcl.decl]/4 的最终 state(用于 C++20)中仍然允许,其中限制是模板化 function的限制(参见[temp.pre]/8中的模板化实体, particularly [temp.pre]/8.3 ), which does not only cover function templates (and function template members of non-templates and template class templates), but also non-template member functions of class templates.
Clang bug report: Clang 错误报告:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.