c++ - 如果使用 "Promotion",为什么隐式转换序列不是最好的 ICS?

标签 c++ operator-overloading implicit-conversion

编译这段代码:

int func( int ) {
 return 1;
}
int func( char ) {
 return 2;
}
struct foo {
  operator int() { // Call to 'func(a)' is ambigous #1
  // operator char() { // Call to 'func(a)' is not ambigous #2
  return 1;
 }
 operator float() {
  return 0.f;
 }
};

int test_it (void) {
 foo a;
 return (func(a)==2);
}

如果我为 foo 定义 int 转换运算符而不是 char,许多编译器会发现调用 func(a) 不明确,只有 1 个编译器发现它没有歧义。

https://godbolt.org/g/zhRJZB

阅读标准,我并不期待,因为:

如果我编译 #2 结构 afoo -> char 转换而来,然后是 char -> char 这是候选集的最佳隐式转换序列 (ICS),由:

(1) foo ->  char : char -> char
(2) foo ->  char : char -> int 
(3) foo ->  float : float -> int
(3) foo ->  float : float -> char

转换 char -> int 是一个提升,所以这个转换 (2) 的排名是“提升”,它比“完全匹配”(1) 更差, float -> int 是 (3) “转换”

如果 #1 改为:

 foo ->  int : int -> int

应该是最好的 ICS,因为:

(1) foo ->  int : int -> int better than 
(3) foo ->  int : int -> char 
(3) foo ->  float : float -> int
(3) foo ->  float : float -> char

所以在这个候选集中,应该只有比其他更好的隐式转换序列。

有人能解释一下为什么代码会模棱两可吗?

最佳答案

因为重载决策不会直接比较这四种转换。

在#2 的情况下,重载决策首先假设 int func(int) 被选中,然后它找到

foo -> char  : char -> int is better than
foo -> float : float -> int

因此,如果选择 int func(int),则会考虑转换 foo -> char : char -> int。类似地,如果选择了 int func(char),那么它会找到

foo -> char  : char -> char is better than
foo -> float : float -> char

因此,如果选择 int func(char),则会考虑转换 foo -> char : char -> char。最后,由于

foo -> char  : char -> char is better than
foo -> char  : char -> int

重载解析最终选择了int func(char)以及转换foo -> char : char -> char


#1 情况类似,除了重载决议无法确定选择哪个转换当它假设选择了 int func(char)。在这种情况下,重载决策引入了一个不明确的转换序列,用于比较对应于两个 func 的隐式转换序列(以确定哪个 func 选择)。模棱两可的转换序列与任何用户定义的转换序列都无法区分,因此结果是模棱两可的。

引自[over.best.ics]/10 :

If several different sequences of conversions exist that each convert the argument to the parameter type, the implicit conversion sequence associated with the parameter is defined to be the unique conversion sequence designated the ambiguous conversion sequence. For the purpose of ranking implicit conversion sequences as described in [over.ics.rank], the ambiguous conversion sequence is treated as a user-defined conversion sequence that is indistinguishable from any other user-defined conversion sequence.

关于c++ - 如果使用 "Promotion",为什么隐式转换序列不是最好的 ICS?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49326292/

相关文章:

c++ - 为什么 C++ 编译器找不到运算符 <<

Scala Option 隐式转换 - 不好的做法或缺少功能?

c++ - 针对 C++ 隐式转换的警告

Scala运算符重载,左侧参数为内置

c++ - 指针或堆对象的二维数组

C++ 增量问题

c++ - 用于插入 moSTLy 排序数据的数据结构,它将保持排序顺序

加号运算符的 C++ 重载

c++ - 存在转换构造函数和运算符并且涉及显式时的行为

c++ - 编译时间计数/模板参数编号