gpt4 book ai didi

c++ - 2 参数函数的重载决策不正确

转载 作者:可可西里 更新时间:2023-11-01 16:39:35 27 4
gpt4 key购买 nike

让我们来看下面的示例程序:

#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 应该完成)中选择版本,而是从 std 使用隐式转换为 float 。但奇怪的是,这只发生在 atan2 调用而不是 sin 调用。

在更大的项目中,这个错误实际上首先发生在我身上,它也发生在其他双参数函数(或者更确切地说是那些有 2 个 half 参数的函数),比如 fmod,但不适用于任何 1 参数函数。同样,在较大的项目中,它也适用于 gcc 4.6/4.7clang 3.1,没有错误,尽管我没有在那里明确测试这个 SSCCE 版本。

所以我的问题是,VS 2012 是否存在这种错误行为(假设它只发生在 2012 并且只发生在 2 参数函数中),还是我监督了重载决议规则中的一些微妙之处(我猜这确实有点棘手)?

编辑:如果我直接使用命名空间 half_float 或将整个事物直接放在全局命名空间中,也会发生这种情况。同样,如果我不使用 using namespace std,也会发生这种情况,但这是将数学函数放入全局命名空间的 VS 实现。

编辑:原始 VC 2012 编译器及其 2012 年 11 月 CTP 都会发生这种情况。

编辑:虽然我不能完全确定这是否真的违反了最严格意义上的标准,但我已经提交了 bug因为它至少与 1 参数函数的定义不一致并且值得 VS-Team 进一步调查。

最佳答案

我想我找到了原因。 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&const half_expr<half>& )和一个可以直接实例化的模板函数。因此后者是优选的。对于 1 参数函数不会发生这种情况,因为对于那些只需要整数参数的通用版本,VS 2012 只为那些使用 std::enable_if 的函数提供。的 std::is_integral .

但我认为标准对于那些“附加重载” 仅针对内置类型提供这一事实有点不清楚。所以最后我仍然不确定 VS 2012 是否因其过于通用的功能而严格违反了标准,或者它是否是提供这些功能的可行实现选项。

编辑: 看起来,已经有 defect report 2086由于标准的措辞不明确,并且正在修复,将对这些额外重载的要求限制为仅算术类型。由于这似乎一直是最初的意图(并且几乎所有现有的实现都实现了)并且它只是措辞不明确,所以我确实认为这是 VS 2012 实现中的一个错误。

关于c++ - 2 参数函数的重载决策不正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14295217/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com