如何显式调用转换类型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或DECLYPE(AUTO)的程序格式不正确。
此用法a.operator auto()
在[dcl.spec.auto]节中不被明确允许,因此它的格式应该是错误的。但是,对于GCC接受的第二种用法,标准并没有说明conversion-type-id
中的conversion-type-id
替换为推导出的类型表示转换函数的名称。换句话说,声明中声明的conversion-function-id
是operator auto
而不是operator int
。前者与声明的声明人id具有相同的标记。根据语法,非限定idoperator auto
应该是该转换函数的名称。那么,如何显式调用这个转换函数呢?当转换函数包含占位符说明符时,是否在标准中未指定转换函数的名称?
解决方案
这似乎指定得不够精确。
- 发自
10.1.7.4 The auto specifier
:
占位符类型可以与函数声明符一起出现在 DECL-说明符-序号、类型-说明符-序号、转换函数-id或 尾随返回类型,在任何这样的声明有效的上下文中。
准确地阅读,您可能会在这里区分";can";和更强的";只能";,即可能为编译器内部功能(严格错误的行为与未指定的行为)的自由度打开空间。
AND3.4.5 class member access
表示:
7如果id表达式是转换函数id,则其 首先在对象的类中查找转换类型id 表达式和名称(如果找到)。
再次为AUTO关键字能否在此上下文中有效地作为完全限定的转换类型ID留下解释空间。
您的问题本身可能需要进一步分支,即
- 运算符auto()用法的重载规则详细是什么,即它是否适用于已在类定义级别上的常规候选人竞争?(Clang和GCC不是这样,除了额外的运算符int().) 之外,它们都先验地接受运算符。
- 是否可以使用引用(您的案例1)的显式成员运算符调用运算符auto(),即它是否具有(唯一的)可访问名称?允许这样做将与该关键字的所有其他显式允许的用例相矛盾。
我在几个clang修订版中看到了对此的显式测试,因此它的行为不是隐式命名约定应用的产物,而是明显需要的行为。
正如已经在评论中提到的,至少与GCC相比,Clang的行为在这里总体上更一致一些,因为这里完全清楚,AUTO关键字用于类型推导,名称/函数id解析在哪里。那里的运算符auto()被作为更显式的自身实体处理,而对于GCC来说,它具有类似于lambda的匿名性,但即使是显式的成员运算符访问方式,它也会参与候选竞争。
相关文章