met*_*fox 34 c++ templates language-lawyer argument-deduction c++17
使用类模板参数推导我们可以写:
std::less Fn;
Run Code Online (Sandbox Code Playgroud)
但是,G ++ 8.2拒绝此代码:
#include <algorithm>
#include <vector>
#include <functional>
int main()
{
std::vector v= { 1, 3, 2, 7, 5, 4 };
std::sort(v.begin(),v.end(),std::greater());
}
Run Code Online (Sandbox Code Playgroud)
发出以下错误:
error: cannot deduce template arguments for 'greater' from ()
Run Code Online (Sandbox Code Playgroud)
Clang ++ 7.0和MSVC 15.8.0在没有警告的情况下编译它.哪个编译器是对的?
xsk*_*xzr 28
GCC错了.已有错误报告.
甲类型说明符的形式的
typename选择 嵌套名称说明符选择 模板名称为推导的类型([dcl.type.class.deduct])的占位符.
一种用于推导的类类型的占位符,也可在所使用的类型说明符-SEQ的新型-ID或类型-ID一个的新的表达,作为简单型说明符在一个显式的类型转换(功能表示法)([expr.type.conv]),或作为模板参数的参数声明中的类型说明符.推断类类型的占位符不应出现在任何其他上下文中.
允许这样的使用.
[temp.arg]/4描述了需要template-id的语法错误,但没有.但是,此处未作为模板ID解析,因此段落不适用.<>std::greater
son*_*yao 14
Clang和MSVC是正确的.由于隐式生成的演绎指南(自C++ 17)和默认模板参数的组合效果,这应该是格式良好的.
(强调我的)
当函数样式转换或变量声明使用不带参数列表的主类模板C的名称作为类型说明符时,推导将按如下方式进行:
- 如果定义了C,则对于在命名主模板中声明的每个构造函数(或构造函数模板)Ci(如果已定义),构造虚构函数模板Fi,使得
- Fi的模板参数是C的模板参数(如果Ci是构造函数模板),Ci的模板参数(也包括默认模板参数)
- Fi的函数参数是构造函数参数
- Fi的返回类型是C,后跟<>中包含的类模板的模板参数
- 如果未定义C或未声明任何构造函数,则添加一个额外的虚构函数模板,如上所述从假设构造函数C()派生
- 在任何情况下,添加如上从假设构造函数C(C)导出的附加虚构函数模板,称为复制推导候选.
然后执行模板参数推导和重载解析以初始化假设类类型的虚构对象,其构造函数签名与引导(返回类型除外)匹配以形成重载集,并且初始化器由上下文提供.执行了哪个类模板参数推导,除了如果初始化列表由类型的单个表达式(可能是cv-qualified)U组成,则省略列表初始化的第一阶段(考虑初始化列表构造函数),其中U是特化C或从C的专业化派生的类
这些虚构的构造函数是假设类类型的公共成员.如果指南是由显式构造函数构成的,则它们是显式的.如果重载解析失败,则程序格式错误.否则,所选F模板特化的返回类型将成为推导出的类模板特化.
给定std::greater(),应用隐式生成的演绎指南,最后选择附加的虚构函数.作为重载解析的结果,void应用默认参数,然后推导出的类型将是void.这意味着std::greater()应该与写作std::greater<void>()或std::greater<>().
顺便说一句:Gcc没有编译std::greater(),但是std::greater{}或者std::greater g;很好,它可能是gcc的错误.