【问题标题】:Ambiguous overload error when using conversion function使用转换函数时出现不明确的过载错误
【发布时间】:2022-01-25 16:21:40
【问题描述】:

我试图通过here 列出的书籍来了解 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;
}

如您所见here,该程序在创建double a 时工作。但是当我尝试创建对象bc 时会出错。

我的问题是:

  1. 为什么我们没有得到对象a 的歧义错误。也就是说,在Name 类中的两个转换运算符中,为什么选择float 版本而不是int 版本。

  2. 我们为什么/如何得到对象 b 的歧义错误,这是一个 long double。这就像a 一样,我怀疑应该调用float 版本,但我们得到了错误。这与上面的double a 案例有何不同。

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

我只是想了解第一个版本为什么/如何工作,而其他两个没有。

【问题讨论】:

  • 我可以看到为什么 c 的情况不起作用,因为它正在缩小,但我不确定为什么允许 a 而不允许 b
  • IMO 隐式提升 floatdouble 是一个原因,operator float() 返回双倍。
  • operator char() 而不是operator int() 的类似行为:int b = Name(); - 好的,long c = Name(); - 模棱两可。 char 提升为 intoperator char() 返回 int

标签: c++ type-conversion overloading implicit-conversion overload-resolution


【解决方案1】:

基本上,跳过一些在这种情况下不相关的东西,重载决策是为了选择用户定义的转换函数来初始化变量,并且(因为转换运算符之间没有其他区别)选择了最好的可行的基于将 的返回值转换为变量类型所需的标准转换序列的排名。


转换int -&gt; double 是一个浮点积分转换,它有秩转换

转换float -&gt; double 是一个浮点促销,它有等级促销

排名promotion优于排名conversion,因此重载决议将选择operator float作为最佳可行重载。


int -&gt; long double 的转换也是一个浮点-积分转换

float -&gt; long double 的转换不是浮点提升(仅适用于转换float -&gt; double)。它是一个 浮点转换,它有等级 conversion

这两个序列现在具有相同的标准转换序列等级,并且没有任何决胜局(我不会讨论)适用,因此重载决议是模棱两可的。


转换int -&gt; bool 是一个布尔转换,它有等级conversion

float -&gt; bool 的转换也是一个布尔转换

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


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


虽然看起来浮点类型之间的转换应该被认为比从整数到浮点类型的转换“更好”,但通常情况并非如此。

【讨论】:

  • 查看this Draft C++17 Standard 中的#7.7 和#7.9 了解官方促销信息。虽然为什么 float -> long double 被排除在外,但我不确定。 (甚至double -> long double。)或herehere 获取最新的在线标准。
  • @AdrianMole 您可以对整体促销提出相同的要求,这也(大部分)仅适用于从较小类型到int 的转换。它只是优先考虑在参数类型未知的 C 函数中执行的默认提升。
  • 所以...你基本上需要博士学位才​​能了解 C++ 中的简单转换、提升和重载解决方案
【解决方案2】:

在这个初始化中

double a = Name();

这里使用了浮动点提升

C++ 17 标准(7.7 浮点提升)

1 float 类型的纯右值可以转换为类型的纯右值 双倍的。值不变。 2 这种转换称为 浮点提升

对于返回 int 类型的对象的转换函数,使用的转换的等级比浮点提升低。

也就是说,具有晋升等级的转换函数比具有转换等级的函数更可行。

在这些声明中

long double b = Name();
bool c = Name();

使用了从 int 和 float 类型到 long double 和 bool 类型的转换。因此,两种转换都不是更好。这两个函数都有转换等级。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-11-18
    • 2021-11-02
    • 1970-01-01
    • 1970-01-01
    • 2010-11-20
    • 2013-06-25
    • 2020-02-29
    • 2019-08-25
    相关资源
    最近更新 更多