使用转换函数时出现模棱两可的重载错误
Ambiguous overload error when using conversion function
我试图通过列出的书籍 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
时运行。但是当我尝试创建对象 b
和 c
时,它给出了错误。
我的问题是:
为什么我们没有得到对象 a
的歧义错误。即在className
中的两个转换运算符中,为什么选择float
版本而不是int
版本。
Why/how 我们是否得到对象 b
的歧义错误,它是一个 long double
。这就像 a
一样,我怀疑应该调用 float
版本,但我们得到了错误。这与上面的 double a
案例有何不同。
Why/how 我们是否得到对象 c
的歧义错误,即 bool
。在这种情况下,我怀疑可能已经选择了 int
版本,但我们却得到了一个错误。这与使用 float
版本转换函数的 double a
版本有何不同。
我只是想了解 why/how 第一个版本有效,但其他两个无效。
本质上,跳过一些在这种情况下不相关的东西,完成重载决策以选择 user-defined 转换函数来初始化变量和(因为转换运算符之间没有其他差异)最好的根据将 return 值转换为变量类型所需的标准转换序列的等级来选择可行的。
转换 int -> double
是一个 floating-integral 转换,其等级为 转换.
转换 float -> double
是 floating-point 促销,排名为 促销。
排名 promotion 优于排名 conversion,因此重载解析将选择 operator float
作为最佳可行过载。
转换int -> long double
也是floating-integral转换。
转换 float -> long double
不是 floating-point 促销(仅适用于转换 float -> double
).相反,它是 floating-point 转换,其排名为 转换。
两个序列现在具有相同的标准转换序列等级,并且 tie-breakers 的 none(我不会通过)适用,因此重载解析是不明确的。
转换 int -> bool
是一个 布尔值转换 ,其等级为 conversion.
转换float -> bool
也是布尔转换。
所以出现和上面一样的情况
有关转换类别和排名的完整列表,请参阅 https://en.cppreference.com/w/cpp/language/overload_resolution#Ranking_of_implicit_conversion_sequences and https://en.cppreference.com/w/cpp/language/implicit_conversion。
虽然看起来 floating-point 类型之间的转换应该被认为比从整数到 floating-point 类型的转换“更好”,但通常情况并非如此。
在此初始化
double a = Name();
有使用浮动积分促销.
C++ 17 标准(7.7 Floating-point 提升)
1 A prvalue of type float can be converted to a prvalue of type
double. The value is unchanged. 2 This conversion is called
floating-point promotion
对于 returns 类型 int
对象的转换函数,使用了比 floating-point 提升级别低的转换。
也就是说,具有提升等级的转换函数比具有转换等级的函数更可行。
在这些声明中
long double b = Name();
bool c = Name();
使用了从int和float类型到long double和bool类型的转换。所以两种转换都不是更好。这两个函数都有转换等级。
我试图通过列出的书籍 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
时运行。但是当我尝试创建对象 b
和 c
时,它给出了错误。
我的问题是:
为什么我们没有得到对象
a
的歧义错误。即在className
中的两个转换运算符中,为什么选择float
版本而不是int
版本。Why/how 我们是否得到对象
b
的歧义错误,它是一个long double
。这就像a
一样,我怀疑应该调用float
版本,但我们得到了错误。这与上面的double a
案例有何不同。Why/how 我们是否得到对象
c
的歧义错误,即bool
。在这种情况下,我怀疑可能已经选择了int
版本,但我们却得到了一个错误。这与使用float
版本转换函数的double a
版本有何不同。
我只是想了解 why/how 第一个版本有效,但其他两个无效。
本质上,跳过一些在这种情况下不相关的东西,完成重载决策以选择 user-defined 转换函数来初始化变量和(因为转换运算符之间没有其他差异)最好的根据将 return 值转换为变量类型所需的标准转换序列的等级来选择可行的。
转换 int -> double
是一个 floating-integral 转换,其等级为 转换.
转换 float -> double
是 floating-point 促销,排名为 促销。
排名 promotion 优于排名 conversion,因此重载解析将选择 operator float
作为最佳可行过载。
转换int -> long double
也是floating-integral转换。
转换 float -> long double
不是 floating-point 促销(仅适用于转换 float -> double
).相反,它是 floating-point 转换,其排名为 转换。
两个序列现在具有相同的标准转换序列等级,并且 tie-breakers 的 none(我不会通过)适用,因此重载解析是不明确的。
转换 int -> bool
是一个 布尔值转换 ,其等级为 conversion.
转换float -> bool
也是布尔转换。
所以出现和上面一样的情况
有关转换类别和排名的完整列表,请参阅 https://en.cppreference.com/w/cpp/language/overload_resolution#Ranking_of_implicit_conversion_sequences and https://en.cppreference.com/w/cpp/language/implicit_conversion。
虽然看起来 floating-point 类型之间的转换应该被认为比从整数到 floating-point 类型的转换“更好”,但通常情况并非如此。
在此初始化
double a = Name();
有使用浮动积分促销.
C++ 17 标准(7.7 Floating-point 提升)
1 A prvalue of type float can be converted to a prvalue of type double. The value is unchanged. 2 This conversion is called floating-point promotion
对于 returns 类型 int
对象的转换函数,使用了比 floating-point 提升级别低的转换。
也就是说,具有提升等级的转换函数比具有转换等级的函数更可行。
在这些声明中
long double b = Name();
bool c = Name();
使用了从int和float类型到long double和bool类型的转换。所以两种转换都不是更好。这两个函数都有转换等级。