如何确定两个优先于重载决议的隐式转换序列?
How to determine two implicit conversion sequences preferred than each other for overload resolution?
我想问一下伴随隐式类型转换的重载解析。这个问题参考cppreference 1 and 2.
似乎一个隐式转换序列最多只有三步将类型T1
(参数类型)转换为T2
(参数类型):
- 零个或一个标准转换序列;
零个或一个用户定义的转换; (我想忽略这一步,因为它与这个问题无关。)
- 零个或一个标准转换序列。
隐式转换序列可以归类为以下之一:
- 一个标准的转换序列(我只对这个基本类型转换案例感兴趣。)
用户自定义转换序列
省略号转换序列
并且,每种类型的标准转换序列都分配了三个等级之一:
- 完全匹配:无需转换,左值右值转换,限定符转换,函数指针转换,自定义class类型到相同的转换class
- 提升:积分提升,浮点提升
- 转换:整型转换、浮点型转换、浮点型整数转换、指针转换、指针到成员转换、布尔型转换、派生类的用户自定义转换class 到它的底部
而且,
The rank of the standard conversion sequence is the worst of the ranks of the standard conversions it holds.
我认为会有这样一种情况,两个隐式转换序列的组成标准转换序列步骤彼此具有不同的等级。所以,恕我直言,我很难确定哪个隐式转换序列比另一个更好。
例如(很遗憾,我想不出一个具体的例子。),
一个隐式转换序列(A)由
组成
- 标准转换序列(A-1)即等级提升.
- 无用户定义的转换顺序
- 标准转换序列(A-2),即等级转换.
另一个隐式转换序列(B)由
组成
- 标准转换序列(B-1)即等级转换.
- 无用户定义的转换顺序
- 标准转换序列(B-2)即等级提升.
在这种情况下,A-1 优于 B-1 但 B-2 优于 A-2。所以,每个 A 和 B 都有自己的偏好。 -> 模棱两可的调用?
OR... A-1 和 B-1 应该首先比较 A-2 和 B-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++ 主要是这样工作的”。如果您需要法律细节(并且在大多数情况下,您 不需要。特别是 围绕重载决议。了解太多这会让您成为糟糕的程序员),那你就得去标准了。
我想问一下伴随隐式类型转换的重载解析。这个问题参考cppreference 1 and 2.
似乎一个隐式转换序列最多只有三步将类型T1
(参数类型)转换为T2
(参数类型):
- 零个或一个标准转换序列;
零个或一个用户定义的转换; (我想忽略这一步,因为它与这个问题无关。)- 零个或一个标准转换序列。
隐式转换序列可以归类为以下之一:
- 一个标准的转换序列(我只对这个基本类型转换案例感兴趣。)
用户自定义转换序列省略号转换序列
并且,每种类型的标准转换序列都分配了三个等级之一:
- 完全匹配:无需转换,左值右值转换,限定符转换,函数指针转换,自定义class类型到相同的转换class
- 提升:积分提升,浮点提升
- 转换:整型转换、浮点型转换、浮点型整数转换、指针转换、指针到成员转换、布尔型转换、派生类的用户自定义转换class 到它的底部
而且,
The rank of the standard conversion sequence is the worst of the ranks of the standard conversions it holds.
我认为会有这样一种情况,两个隐式转换序列的组成标准转换序列步骤彼此具有不同的等级。所以,恕我直言,我很难确定哪个隐式转换序列比另一个更好。
例如(很遗憾,我想不出一个具体的例子。),
一个隐式转换序列(A)由
组成- 标准转换序列(A-1)即等级提升.
- 无用户定义的转换顺序
- 标准转换序列(A-2),即等级转换.
另一个隐式转换序列(B)由
组成- 标准转换序列(B-1)即等级转换.
- 无用户定义的转换顺序
- 标准转换序列(B-2)即等级提升.
在这种情况下,A-1 优于 B-1 但 B-2 优于 A-2。所以,每个 A 和 B 都有自己的偏好。 -> 模棱两可的调用?
OR... A-1 和 B-1 应该首先比较 A-2 和 B-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++ 主要是这样工作的”。如果您需要法律细节(并且在大多数情况下,您 不需要。特别是 围绕重载决议。了解太多这会让您成为糟糕的程序员),那你就得去标准了。