303*_*303 3 c++ language-lawyer c++20
下面的代码示例合法吗?C++20 标准对此有何规定?
template<typename...>
struct s { s(auto) {} };
s(auto) -> s<> requires true;
static_assert(sizeof(s{true})); // clang nope, gcc ok, msvc ok/crash
Run Code Online (Sandbox Code Playgroud)
来自 Clang 的错误消息:
<source>:7:25: error: deduction guide cannot have a requires clause
7 | s(auto) -> s<> requires true;
|
Run Code Online (Sandbox Code Playgroud)
用户定义的推导指南是否可以受到尾随的 require 子句的约束?
目前,没有。演绎指南本身不声明template-head ,仅引用template-name。从[temp.deduct.guide]/1,注意到 asimple-template-id也只是指模板专业化:
当模板名称作为推导类类型 ([dcl.type.class.deduct]) 的类型说明符出现时,将使用推导指南。通过名称查找找不到推导指南。相反,当执行类模板参数推导([over.match.class.deduct])时,会考虑为类模板声明的所有可达推导指南。
Run Code Online (Sandbox Code Playgroud)deduction-guide: explicit-specifier_opt template-name ( parameter-declaration-clause ) -> simple-template-id ;
另一方面,命名模板可能受到限制,如[temp.names]/8所涵盖的那样
当 simple-template-id 的 template-name 命名受约束的非函数模板或受约束的模板 template-parameter 时,并且 simple-template-id 中的所有模板参数都是非依赖的([temp.dep.temp ]),受约束模板的关联约束([temp.constr.decl])应得到满足([temp.constr.constr])。
因此,Clang 拒绝你的例子是正确的。
正如 @user17732522 所指出的,有一个开放的 CWG 问题CWG 2707,它建议更改演绎指南的语法,以允许它们具有尾随的需求子句。尽管 CWG 计划在今年夏天(2023 年 6 月)的 WG21 瓦尔纳会议期间讨论该问题,但自启动以来尚未出现任何活动,但似乎时间不够。
2707. 演绎指南不能有尾随的 require 子句
[...]
演绎指南的语法不允许但应该允许尾随的 require 子句:
Run Code Online (Sandbox Code Playgroud)deduction-guide: explicit-specifieropt template-name ( parameter-declaration-clause ) -> simple-template-id ;建议的解决方案:
将 13.7.2.3 [temp.deduct.guide] 第 1 段中的语法更改如下:
Run Code Online (Sandbox Code Playgroud)deduction-guide: explicit-specifier_opt template-name ( parameter-declaration-clause ) requires-clause_opt -> simple-template-id ;