繁体   English   中英

如何确定两个隐式转换序列优先于重载解析?

[英]How to determine two implicit conversion sequences preferred than each other for overload resolution?

我想质疑伴随隐式类型转换的重载决议。 这个问题是指 cppreference 12

似乎隐式转换序列最多需要三个步骤将类型T1 (参数类型)转换为T2 (参数类型):

  1. 零个或一个标准转换序列;
  2. 零个或一个用户定义的转换; ( 我想忽略这一步,因为它与这个问题无关。)
  3. 零个或一个标准转换序列。

隐式转换序列可以归类为以下之一:

  • 标准转换序列(我只对这种基本类型转换案例感兴趣。)
  • 用户定义的转换序列
  • 省略号转换序列

并且,每种类型的标准转换序列都被分配了三个等级之一:

  1. 完全匹配:无需转换、左值到右值转换、限定转换、函数指针转换、类类型到同一类的用户定义转换
  2. 提升:积分提升、浮点提升
  3. 转换:整数转换、浮点转换、浮点转换、指针转换、指针到成员转换、布尔转换、派生类到其基类的用户定义转换

和,

标准转换序列的等级是它所拥有的标准转换等级中最差的。

我认为会有一种情况,两个隐式转换序列的组成标准转换序列步骤彼此具有不同的等级。 因此,恕我直言,我很难确定哪个隐式转换序列比另一个更受欢迎。

例如(不幸的是,我无法想出一个具体的例子。),

隐式转换序列 ( A ) 包括

  1. 标准转换序列 ( A-1 ),即等级提升
  2. 没有用户定义的转换序列
  3. 标准转换序列( A-2 ),即等级转换

另一个隐式转换序列 ( B ) 包括

  1. 标准转换序列( B-1 ),即等级转换
  2. 没有用户定义的转换序列
  3. 标准转换序列( B-2 ),即等级提升

在这种情况下, A-1B-1 好,B-2A-2 好 所以, AB都有自己的偏好。 -> 模棱两可的电话?

或... A-1B-1应该首先比较A-2B-2 那么,我们应该停止在这里进行贪婪的比较吗? -> A被选中了?


更新:为了解释我对这些概念的理解......

// [ what is overall rank for standard coversion sequence n  ]
// [          standard conversion sequence n(up to 2)        ]
// [     each conversion's rank in a std conv sequence n     ]
// [ what conversions are performed in a std conv sequence n ]
// [    how source type T1 is converted to target type T2    ]

// [            promotion                ][       exact match    ]
// [          std conv seq1              ][     std conv seq2    ]
// [  promotion  |     exact match       ][        exact match   ]
// [  promotion  |  const qualification  ][     no conversion    ]
// [char   ->   int    ->   const int    ->        const int     ]
void f(const int){
    std::cout << "f(const int)" << std::endl;
}

// [   promotion   ][                conversion                  ]
// [ std conv seq1 ][               std conv seq2                ]
// [   promotion   ||      conversion      |     exact match     ]
// [   promotion   ||  integral conversion, const qualification  ]
// [char   ->     int       ->     long    ->    const long      ]
void f(const long){
    std::cout << "f(const long)" << std::endl;
}

int main() {
    // For the first sequence, the two functions have same 2nd rank, 'promotion'.
    // So, we couldn't determine which function will be called yet.
    // But, for the second sequence, the former has 1st rank 'exact match'
    // and the latter has 3rd rank 'conversion'. So the former will be called.
    f('c'); // prints "f(const int)"
}

Cppreference 是一个有用的参考站点,但它不是 C++ 标准。 它具有大部分准确的信息,但在简化标准的复杂性时,可能会在边缘附近丢失一些细节。

我将引用 C++17(因为我没有可以链接到的 C++11 网站),但措辞没有发生有意义的变化。

[over.best.ics]/3将隐式转换序列定义为

格式良好的隐式转换序列是以下形式之一:

  • 一个标准的转换序列,
  • 用户定义的转换序列,或
  • 省略号转换序列。

这或多或少是 Cppreference 所说的,但这里更明确地表明您要么拥有一个标准转换序列,要么拥有一个用户定义的转换。 用户定义的转换本身包括两个标准的转换序列

用户定义的转换序列由初始标准转换序列后跟用户定义的转换 ([class.conv]) 和第二个标准转换序列组成。

Cppreference 使您看起来可以在没有用户定义转换的情况下拥有两个标准转换序列,但您不能。 如果没有用户定义的转换在起作用,则您只有一种标准转换。

不要试图将 Cppreference 视为 C++ 的合法定义。 将其更多地视为“C++ 的工作方式主要是这样”。 如果您需要合法的细节(并且在大多数情况下,您不需要尤其是在重载解析方面。对此了解太多会使您成为一个糟糕的程序员),那么您必须遵循标准。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM