如何确定两个优先于重载决议的隐式转换序列?

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

我想问一下伴随隐式类型转换的重载解析。这个问题参考cppreference 1 and 2.

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

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

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

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

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

而且,

The rank of the standard conversion sequence is the worst of the ranks of the standard conversions it holds.

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

例如(很遗憾,我想不出一个具体的例子。),

一个隐式转换序列(A)由

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

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

组成
  1. 标准转换序列(B-1)即等级转换.
  2. 无用户定义的转换顺序
  3. 标准转换序列(B-2)即等级提升.

在这种情况下,A-1 优于 B-1B-2 优于 A-2。所以,每个 AB 都有自己的偏好。 -> 模棱两可的调用?

OR... 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(因为我没有可以 link 访问的 C++11 网站),但措辞没有有意义的改变。

[over.best.ics]/3 defines an implicit conversion sequence as:

A well-formed implicit conversion sequence is one of the following forms:

  • a standard conversion sequence,
  • a user-defined conversion sequence, or
  • an ellipsis conversion sequence.

这或多或少是 Cppreference 所说的,但这里更明确地说,您要么恰好有 一个 标准转换序列,要么恰好有 one 用户自定义转换。用户自定义转换自身includes two standard conversion sequences:

A user-defined conversion sequence consists of an initial standard conversion sequence followed by a user-defined conversion ([class.conv]) followed by a second standard conversion sequence.

Cppreference 使您似乎可以拥有两个标准转换序列 而无需 用户定义的转换,但实际上您不能。如果播放中没有用户定义的转换,则只有一个标准转换。

不要试图将 Cppreference 解读为 C++ 的合法定义。更多地把它想象成“C++ 主要是这样工作的”。如果您需要法律细节(并且在大多数情况下,您 不需要特别是 围绕重载决议。了解太多这会让您成为糟糕的程序员),那你就得去标准了。