使用转换函数时出现不明确的重载错误

use*_*570 12 c++ overloading type-conversion overload-resolution implicit-conversion

我试图通过这里列出的书籍来理解 C++ 中的重载解析。我为了澄清我的概念而写的一个这样的例子,其输出我无法理解,如下所示。


#include <iostream>
struct Name 
{
  operator int() 
  {
      std::cout<<"Name's int version called"<<std::endl;
      return 4;
  }
  operator float() 
  {
      std::cout<<"Name's float version called"<<std::endl;
      return 1.1f;
  }
  
};
int main()
{
    
    double a = Name(); //this works and calls Name's float version. But WHY ISN'T THIS AMBIGIOUS?
    long double b = Name();  //this does not work. WHY IS THIS AMBIGIOUS?
    bool c = Name();  //this does not work. WHY IS THIS AMBIGIOUS? 
     
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

正如您在这里所看到的,该程序在创建double a. 但是当我尝试创建对象时bc它给出了错误。

我的问题是:

  1. 为什么我们没有得到 object 的歧义错误a。也就是说,在 class 的两个转换运算符Name中,为什么float选择 version 而不是intversion。

  2. b为什么/如何获得long double. 就像 for 一样a,我怀疑应该调用该float版本,但我们得到了错误。这和上面的例子有什么不同double a

  3. 为什么/如何获得对象的歧义错误,c该错误是bool. 在这种情况下,我怀疑int可以选择该版本,但我们收到了错误。double a这与工作并使用float转换功能的版本有何不同。

我只是想了解第一个版本为何/如何工作,但其他两个则不然。

use*_*522 11

本质上,跳过一些在这种情况下不相关的内容,进行重载解析以选择用户定义的转换函数来初始化变量,并且(因为转换运算符之间没有其他差异)根据以下条件选择最佳可行的函数:将返回值转换为变量类型所需的标准转换序列的等级。


该转换int -> double浮点积分转换,具有秩转换

该转换float -> double浮点提升,具有等级提升

排名提升优于排名转换,因此重载决策将选择operator float最佳可行的重载。


该转换int -> long double也是浮点积分转换

转换float -> long double不是浮点提升(仅适用于 conversion )。相反,它是具有等级转换的浮点转换float -> double

现在,两个序列都具有相同的标准转换序列等级,并且没有任何决胜局(我不会经历)适用,因此重载解析是不明确的。


该转换int -> bool是具有排名转换的布尔转换

该转换float -> bool也是布尔转换

因此,就会出现与上述相同的情况。


有关转换类别和排名的完整列表,请参阅https://en.cppreference.com/w/cpp/language/overload_resolution#Ranking_of_implicit_conversion_sequenceshttps://en.cppreference.com/w/cpp/language/implicit_conversion 。


尽管浮点类型之间的转换似乎应该被认为比从整型到浮点类型的转换“更好”,但通常情况并非如此。