Chr*_*ica 9 c++ overload-resolution visual-studio-2012
我们来看下面的示例程序:
#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);
}
Run Code Online (Sandbox Code Playgroud)
在VS 2010中,这编译得很好(暂时忽略明显的链接器错误).但在VS 2012中,这给了我:
错误C2440:'转换':无法从'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参数函数),或者我是否监督了重载决策规则中的一些细微之处(这确实可以得到一个有点棘手,我想)?
编辑:如果我直接using namespace half_float
或直接将全部内容放在全局命名空间中,也会发生这种情况.同样,如果我不这样做也会发生using namespace std
,但这是VS实现将数学函数放在全局命名空间中.
编辑:它与原始的VC 2012编译器以及2012年11月的CTP一起发生.
编辑:虽然我并不完全确定它是否真的违反了严格意义上的标准,但我根据答案的结果提出了一个错误,因为它至少与1-的定义不一致参数函数并值得VS -Team 进一步调查.
我想我找到了原因.C++标准在第26.8节[c.math]中说,对于C库的数学函数,
应有足够的额外过载以确保:
- 如果对应于double参数的任何参数的类型为long double,则对应于double参数的所有参数都有效地转换为long double.
- 否则,如果对应于double参数的任何参数具有double类型或整数类型,则对应于double参数的所有参数都将有效地转换为double.
- 否则,对应于double参数的所有参数都被有效地转换为float.
这也可以在atan2文档中看到.
VS 2012通过使用以下形式的通用函数模板提供这些重载:
template<typename T,typename U> common_float_type<T,U>::type atan2(T, U);
Run Code Online (Sandbox Code Playgroud)
所以我们有一个模板函数,它的实例化涉及一个隐式转换(from half&
to const half_expr<half>&
)和一个可以直接实例化的模板函数.因此后者是优选的.对于1参数函数不会发生这种情况,因为对于那些只需要为积分参数的通用版本,由VS 2012仅为那些使用a std::enable_if
的人提供std::is_integral
.
但我认为标准有点不清楚,那些"额外的重载"只能用于内置类型.所以最后我还不确定VS 2012是否严格违反了标准及其过于通用的功能,或者它是否是提供这些功能的可行实施选项.
编辑:看起来,已经存在缺陷报告2086,因为该标准的措辞不清楚,并且正在进行修复,将这些额外重载的要求仅限于算术类型.由于这似乎一直是最初的意图(并且几乎所有现有实现都已实现)并且仅仅是措辞不清楚,我确实认为这是VS 2012实施中的一个错误.
归档时间: |
|
查看次数: |
498 次 |
最近记录: |