如何显式调用转换类型id包含占位符说明符的转换函数

2022-03-07 00:00:00 language-lawyer c++
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-idoperator auto而不是operator int。前者与声明的声明人id具有相同的标记。根据语法,非限定idoperator auto应该是该转换函数的名称。那么,如何显式调用这个转换函数呢?当转换函数包含占位符说明符时,是否在标准中未指定转换函数的名称?


解决方案

这似乎指定得不够精确。

  1. 发自10.1.7.4 The auto specifier
占位符类型可以与函数声明符一起出现在 DECL-说明符-序号、类型-说明符-序号、转换函数-id或 尾随返回类型,在任何这样的声明有效的上下文中。

准确地阅读,您可能会在这里区分";can";和更强的";只能";,即可能为编译器内部功能(严格错误的行为与未指定的行为)的自由度打开空间。

AND3.4.5 class member access表示:

7如果id表达式是转换函数id,则其 首先在对象的类中查找转换类型id 表达式和名称(如果找到)。

再次为AUTO关键字能否在此上下文中有效地作为完全限定的转换类型ID留下解释空间。

您的问题本身可能需要进一步分支,即

  1. 运算符auto()用法的重载规则详细是什么,即它是否适用于已在类定义级别上的常规候选人竞争?(Clang和GCC不是这样,除了额外的运算符int().)
  2. 之外,它们都先验地接受运算符。
  3. 是否可以使用引用(您的案例1)的显式成员运算符调用运算符auto(),即它是否具有(唯一的)可访问名称?允许这样做将与该关键字的所有其他显式允许的用例相矛盾。

我在几个clang修订版中看到了对此的显式测试,因此它的行为不是隐式命名约定应用的产物,而是明显需要的行为。

正如已经在评论中提到的,至少与GCC相比,Clang的行为在这里总体上更一致一些,因为这里完全清楚,AUTO关键字用于类型推导,名称/函数id解析在哪里。那里的运算符auto()被作为更显式的自身实体处理,而对于GCC来说,它具有类似于lambda的匿名性,但即使是显式的成员运算符访问方式,它也会参与候选竞争。

相关文章