dfr*_*fri 3 c++ gcc clang language-lawyer c++20
考虑以下示例:
void f() requires true { }
int main() { f(); }
Clang (1) ( DEMO ) 接受这个程序,而 GCC (1) ( DEMO ) 拒绝它并出现以下错误:
Run Code Online (Sandbox Code Playgroud)error: constraints on a non-templated function
请注意,约束表达式实际上可以在 Clang 的情况下使用,因为以下程序被 Clang 拒绝:
void f() requires false { }
int main() { f(); }  //  // error: no matching function for call to 'f'
Clang 注意到声明f的不是候选者,因为约束不满足(因为它是f()调用的候选者;DEMO)。
(1) GCC HEAD 11.0.0 20210124 和 Clang HEAD 12.0.0 (20210124), -std=c++20.
除非另有说明,否则以下所有标准参考均指N4861(2020 年 3 月布拉格后工作草案/C++20 DIS)。
这是一个 Clang 错误,根据[dcl.decl]/4(以及[temp.constr.decl]/1)[强调我的] ,GCC 拒绝该程序是正确的:
可选要求子句中的INIT-声明符或 构件声明符 仅当声明符声明一个模板函数应存在([dcl.fct])。当出现在声明符之后时,requires-clause被称为尾随 requires-clause。[...]
同一段落还包含一个(非规范性)示例,明确指出 OP 的示例格式不正确:
[示例:
Run Code Online (Sandbox Code Playgroud)void f1(int a) requires true; // error: non-templated function template<typename T> auto f2(T a) -> bool requires true; // OK // ...—结束示例]
我们可能会注意到,在(成为 C++20)工作草案的早期版本N4810 中,[dcl.decl]/4 对允许出现 requires 子句的位置有较弱的要求:
init-declarator或member-declarator 中的可选requires-clause(第 13 条)在声明符未声明函数时不应出现(9.2.3.5)。[...]
[示例:
Run Code Online (Sandbox Code Playgroud)void f1(int a) requires true; // OK // ...—结束示例]
其中 OP 用例的非规范示例被明确显示为格式良好。最初的意图可以说是允许基于类模板的模板参数来约束类模板的非模板成员函数:
#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
} 
这仍允许在最终的状态(用于C ++ 20)的[dcl.decl]在N4861,其中该限制是为了一个/ 4模板函数(参见模板实体中[temp.pre] / 8,特别是[temp.pre]/8.3 ),它不仅涵盖了函数模板(以及非模板和模板类模板的函数模板成员),还包括类模板的非模板成员函数。
Clang 错误报告: