代码之家  ›  专栏  ›  技术社区  ›  xmh0511

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

  •  5
  • xmh0511  · 技术社区  · 3 年前
    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 在哪里 conversion-type-id 被推导出的类型所取代 表示转换函数的名称。换句话说,宣布 转换函数id 在声明中 operator auto 而不是 operator int 前者与声明的声明者id具有相同的标记。根据语法,不合格的id 操作员自动 应该是该转换函数的名称。那么,如何显式调用这个转换函数呢?当转换函数包含占位符说明符时,标准中是否未明确指定转换函数的名称?

    0 回复  |  直到 3 年前
        1
  •  10
  •   Secundi    3 年前

    看来,这还不够精确。

    1. 10.1.7.4 The auto specifier :

    占位符类型可以与函数声明符一起出现在 decl说明符seq、类型说明符seq, 转换函数id ,或 尾随返回类型,在任何此类声明器有效的上下文中。

    准确地说,人们可能会在这里区分“can”和更强的“can only”,即可能为编译器内部函数(严格错误与未指定行为)的自由度开辟空间。

    还有 3.4.5 class member access 说:

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

    如果auto关键字在此上下文中是否可以有效地成为完全限定的转换类型id,那么这再次为解释留下了空间。

    你的问题本身可能需要进一步细分,即

    1. 运算符auto()使用的重载规则是什么,即它是否应该在类定义级别上用于常规候选人竞争?(Clang和Gcc的情况并非如此,除了额外的运算符int()之外,它们都先验地接受运算符…)
    2. 运算符auto()是否可以用显式成员运算符引用(您的情况1)来调用,即它是否有一个(唯一的)可访问名称?允许这样做将与该关键字的所有其他明确允许的用例相矛盾。

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

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