其他分享
首页 > 其他分享> > c – 2参数函数的重载分辨率不正确

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:

  1. 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.
  2. 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.
  3. 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