c – 2参数函数的重载分辨率不正确
作者:互联网
我们来看下面的示例程序:
#include <cmath>
namespace half_float
{
template<typename T> struct half_expr {};
struct half : half_expr<half>
{
operator float() const;
};
template<typename T> half sin(const half_expr<T>&);
template<typename T> half atan2(const half_expr<T>&, const half_expr<T>&);
}
using namespace std;
using half_float::half;
int main()
{
half a, b;
half s = sin(a);
half t = atan2(a, b);
}
在VS 2010中,这编译得很好(暂时忽略明显的链接器错误).但在VS 2012中,这给了我:
error C2440: ‘conversion’ : cannot convert from ‘float’ to
‘half_float::half’
因此,似乎重载解析不会从命名空间half_float(ADL应该完成)中选择版本,而是使用隐式转换为float的std中的版本.但奇怪的是,这只发生在atan2呼叫而不是罪恶呼叫.
在较大的项目中,这个错误实际上首先发生在我身上,对于其他2参数函数(或者更确切地说具有2个半参数的函数)也会发生,例如fmod,但不适用于任何1参数函数.同样在较大的项目中,它也适用于gcc 4.6 / 4.7和clang 3.1而没有错误,尽管我没有在那里明确地测试这个SSCCE版本.
所以我的问题是,这是VS 2012方面的错误行为(假设它只发生在2012年,仅用于2参数函数),或者我是否监督了重载决策规则中的一些细微之处(这确实有点棘手) , 我猜)?
编辑:如果我直接使用命名空间half_float或直接将全部内容放在全局命名空间中,也会发生这种情况.同样,如果我没有使用命名空间std也会发生这种情况,但这是VS实现将数学函数放在全局命名空间中.
编辑:它与原始的VC 2012编译器以及2012年11月的CTP一起发生.
编辑:虽然我并不完全确定它是否真的违反了严格意义上的标准,但我已根据我的答案中的调查结果提交了bug,因为它至少与1-的定义不一致论证功能并值得VS团队进一步调查.
解决方法:
我想我找到了原因. C标准在第26.8节[c.math]中说,对于C库的数学函数,
there shall be additional overloads sufficient to ensure:
- If any argument corresponding to a double parameter has type long double, then all arguments corresponding to double parameters are
effectively cast to long double.- Otherwise, if any argument corresponding to a double parameter has type double or an integer type, then all arguments corresponding to
double parameters are effectively cast to double.- Otherwise, all arguments corresponding to double parameters are effectively cast to float.
这也可以在atan2 documentation中看到.
VS 2012通过使用以下形式的通用函数模板提供这些重载:
template<typename T,typename U> common_float_type<T,U>::type atan2(T, U);
因此,我们有一个模板函数,其实例化将涉及隐式转换(从half&到half half_expr< half>&和)以及可以直接实例化的模板函数.因此后者是优选的.对于1参数函数不会发生这种情况,因为对于那些只需要整数参数的通用版本,由VS 2012仅为那些使用std :: enable_if的std :: is_integral的人提供.
但我认为标准有点不清楚,那些“额外的重载”只能用于内置类型.所以最后我还不确定VS 2012是否严格违反了标准及其过于通用的功能,或者它是否是提供这些功能的可行实施选项.
编辑:看起来,标准的措辞不清楚已经有了defect report 2086,修正就是这样,将这些额外重载的要求仅限于算术类型.由于这似乎一直是最初的意图(并且几乎所有现有实现都已实现)并且仅仅是措辞不清楚,我确实认为这是VS 2012实施中的一个错误.
标签:c,visual-studio-2012,overload-resolution 来源: https://codeday.me/bug/20191007/1868627.html