在N4659的16.3.3.1隐式转换序列中写道:10如果存在几个将参数转换为参数类型的不同转换序列,则与参数关联的隐式转换序列被定义为唯一指定的模棱两可的转换序列。 为了按照16.3.3.2所述的顺序对隐式转换序列进行排名,认为模棱两可的转换序列是一个无法区分于任何其他用户定义的转换序列的用户定义的转换序列[注:此规则防止函数因其参数的模糊转换序列而变得不可行]。 如果选择使用具有模糊转换序列的函数作为最佳可行函数,则调用将是不正确的,因为通话中的一个参数的转换是模棱两可的。
此简单示例引发问题。
让我们在这里机械地应用上述规则。
这似乎毫无意义。自然的期望是选择
那么,我理解错了什么?
(当前草案的相应部分是12.3.3.1)
这条规则和它引入的模棱两可的转换序列概念的预期目的是什么?
文本中提供的注释说明了这条规则的目的是“防止由于一个参数的模糊转换序列导致函数成为不可行的”。嗯......这实际上是什么意思呢?可行函数的概念在文件的前面的部分中定义。它根本不依赖于转换的模糊性(每个参数的转换必须存在,但它们不必是明确的)。似乎没有规定一个可行的函数可以以某种方式后来“变得不可行”(既不因为有些模糊也不因为其他任何原因)。可行的函数被枚举,它们相互竞争以遵循某些规则并且如果有单个“赢家”,则解决方案将成功。在此过程中,一个可行的函数可能(或需要)不能成为一个不可行的函数。
所提供的示例并没有提供太多启示(即不清楚以上规则在该示例中扮演了什么角色)。
此简单示例引发问题。
struct S
{
operator int() const { return 0; };
operator long() const { return 0; };
};
void foo(int) {}
int main()
{
S s;
foo(s);
}
让我们在这里机械地应用上述规则。
foo
是一个可行的函数。从参数类型S
到参数类型int
有两个隐式转换序列:S -> int
和S -> long -> int
。这意味着根据上述规则,我们必须将它们“打包”成一个多义转换序列。然后我们得出结论,foo
是最佳可行函数。然后我们发现它使用了我们的多义转换序列。因此,根据上述规则,代码是不合法的。这似乎毫无意义。自然的期望是选择
S -> int
转换,因为它比S -> long -> int
转换排名更高。我所知道的所有编译器都遵循这种“自然”的重载解析。那么,我理解错了什么?
-> int
和-> long
部分建立相应规则的说明是:“使用重载决议来选择要调用的转换函数”。(注意,这是一个嵌套的重载决议,具有自己的隐式转换序列,不应与foo
的决议混淆。)在这种情况下,重载决议使用一种平局解决方法进行选择,即选取了operator int
,因为int -> int
比long -> int
更好。因此,在这里没有使用operator long
的用户定义转换序列。 - Johannes Schaub - litb