c++ - 如何显式调用转换类型 ID 包含占位符说明符的转换函数
问题描述
struct A{
operator auto(){
return 0;
}
};
int main(){
A a;
a.operator auto(); // #1
a.operator int(); // #2
}
GCC接受 #2 是显式调用转换函数的正确方法,而Clang接受 #1。
#1
由于以下规则,这似乎是不正确的:
dcl.spec.auto#6
在本节未明确允许的上下文中使用 auto 或 decltype(auto) 的程序是格式错误的。
a.operator auto()
[dcl.spec.auto] 部分没有明确允许这种用法,因此它应该是格式错误的。但是,对于 GCC 接受的第二种用法,标准并没有说用推导类型替换conversion-function-id
的whereconversion-type-id
表示转换函数的名称。换句话说,声明中声明的不是. 前者与声明的 declarator-id 具有相同的标记。根据语法,unqualified-id应该是那个转换函数的名字。那么,如何显式调用这个转换函数呢?当转换函数包含占位符说明符时,它是否在标准中未明确说明转换函数的名称?conversion-function-id
operator auto
operator int
operator auto
解决方案
似乎,这没有足够精确地指定。
- 来自
10.1.7.4 The auto specifier
:
占位符类型可以与 decl-specifier-seq、type-specifier-seq、conversion-function-id或 trailing-return-type 中的函数声明符一起出现,在此类声明符有效的任何上下文中。
仔细阅读,人们可能会在这里区分“can”和更强的“can only”,即可能为编译器内在函数的自由度打开空间(严格错误与未指定的行为)。
并3.4.5 class member access
说:
7 如果id-expression 是conversion-function-id,则首先在对象表达式的类中查找其conversion-type-id,如果找到,则使用名称。
如果 auto 关键字在此上下文中可以有效地成为完全限定的转换类型 ID,则再次留下解释空间。
您的问题本身可能必须进一步分支,即
- 运算符 auto() 使用的详细重载规则是什么,即它是否应该可用于已经在类定义级别上的常规候选人竞争?(Clang 和 Gcc 不是这种情况,除了额外的运算符 int() 之外,它们都先验地接受运算符 ...)
- 可以使用显式成员运算符引用(您的情况 1)调用运算符 auto(),即有效地,它是否具有(唯一)可访问名称?允许这将与关键字的所有其他明确允许的用例相矛盾。
我已经在几个 clang 修订版中看到了对此的明确测试,因此它的行为不是隐式命名约定应用的人工制品,而是明显需要的行为。
正如评论中已经提到的,至少与 gcc 相比,Clang 的行为在这里更加一致,因为它在那里完全清楚,auto 关键字用于类型推导以及名称/函数 ID 解析的位置。那里的操作符 auto() 被作为一个更明确的自己的实体来处理,而对于 gcc,它具有类似于 lambda 的匿名字符,但即使对于显式成员操作符访问方式,它也会参与候选人竞争。
推荐阅读
- github - 如何在 vscode 中禁用 github 登录
- node.js - 如何将节点 js 项目上传到 aws lambda?
- angular - Angular 8 ExpressionChangedAfterItHasBeenCheckedError 反应形式的无线电验证
- python - 请求到数据框
- arrays - 反应,无法访问对象中的数组
- php - 我们如何通过姓氏获取显示名称?
- python - 使用 csv.DictWriter 将字典的 {'key':value} 对写入 .csv 文件并得到“ ValueError: dict contains fields not in fieldnames: '
- pipe - 在终端中使用 Cat 创建文件并将文件传递给另一个命令
- php - Laravel:仅当给定的资源实例是顶级时才加载 API 资源密钥
- python - 无法在 python 中导入 .so 文件