通过类模板参数推导,我们可以编写:
std::less Fn;
但是,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());
}
发出以下错误:
error: cannot deduce template arguments for 'greater' from ()
Clang ++ 7.0和MSVC 15.8.0无需警告即可对其进行编译。哪个编译器是正确的?
答案 0 :(得分:28)
GCC错误。已经有一个bug report。
格式为
typename
的类型说明符 opt 嵌套名称说明符 < sub> opt template-name 是推导的类类型([dcl.type.class.deduct])的占位符。
推断出的类类型的占位符也可以在 new-type-id 或 type-id < new-expression 的/ em>,作为 simple-type-specifier 的显式类型转换(功能符号)([expr。 type.conv]),或者作为 template-parameter 的 parameter-declaration 中的 type-specifier 。推导类类型的占位符不得出现在任何其他上下文中。
允许这种使用。
[temp.arg]/4描述了语法错误,该错误是 template-id 所必需的,但没有<>
。但是,这里std::greater
不能解析为 template-id ,因此该段落不适用。
答案 1 :(得分:14)
Clang和MSVC是正确的。由于implicitly-generated deduction guides (since C++17)和默认模板参数的组合作用,因此该格式应正确。
(重点是我的)
当函数式强制转换或变量声明使用名称时 没有参数列表作为类型的主类模板C的类型 说明符,将进行以下推断:
- 如果定义了C,则对于在命名的主模板(如果已定义)中声明的每个构造器(或构造器模板)Ci, 构造功能模板Fi,使得
Fi的
- 模板参数是C的模板参数,后跟(如果Ci是构造函数模板) of Ci(还包括默认模板参数)
- Fi的功能参数是构造函数参数
- Fi的返回类型为C,后跟<>
中包含的类模板的模板参数- 如果未定义C或未声明任何构造函数,则会添加一个附加的虚构函数模板,该模板如上所述从 假设的构造函数C()
- 在任何情况下,都会添加一个从假设的构造函数C(C)派生的上述虚构函数模板,称为副本 演绎候选者。
然后执行模板参数推导和重载解析 用于初始化假设类类型的虚构对象, 其构造函数签名与指南匹配(返回类型除外) 为了形成一个过载集,而初始化程序是 由上下文提供,在该上下文中类模板参数推导为 执行,除了列表初始化的第一阶段 如果(考虑初始化器列表构造函数) 初始化列表由一个类型的表达式组成(可能是 cv限定)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的错误。