让我们看下面的示例程序:
#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中,这给了我:
错误 C2440:“conversion”:无法从“float”转换为“half_float::half”
因此,重载解析似乎不是从命名空间中选择版本half_float
(ADL 应该完成),而是从std
使用隐式转换到float
. 但奇怪的是,这只发生在atan2
通话中而不是sin
通话中。
在较大的项目中,这个错误实际上首先发生在我身上,它也发生在其他 2 参数函数(或者更确切地说具有 2 个half
参数的函数)中,例如fmod
,但不会发生在任何 1 参数函数中。同样,在较大的项目中,它也适用于gcc 4.6/4.7和clang 3.1,没有错误,尽管我没有在那里明确测试这个 SSCCE 版本。
所以我的问题是,这种错误行为是在VS 2012方面(假设它只发生在2012 年并且只发生在 2-argument 函数中),还是我监督了重载解决规则中的一些微妙之处(这确实可以得到一个有点棘手,我猜)?
编辑:如果我直接using namespace half_float
或直接将整个东西放在全局命名空间中,也会发生这种情况。同样,如果我不是using namespace std
,它也会发生,但这更像是将数学函数放在全局命名空间中的 VS 实现。
编辑:它发生在原始VC 2012编译器以及它的2012 年 11 月 CTP中。
编辑:虽然我不完全确定它是否真的违反了最严格意义上的标准,但我已经根据我的回答中的发现提交了一个错误,因为它至少与 1- 的定义不一致参数功能,值得VS团队进一步调查。