以下代码编译并生成一个调用std::isnan,请参见此处
#include <iostream>
#include <cmath>
namespace foo {
template<class T>
inline bool isnan (T x)
{ //Fake function returning always true
std::cout << "foo::isnan" << std::endl;
return true;
}
}
using foo::isnan;
using std::isnan;
int main () {
std::cout << isnan(5.5f) << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
为什么这个函数调用不明确?
看看cmath.h,我看到:
template<typename _Tp>
inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value,
int>::__type
isnan(_Tp __f)
{
typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
return __builtin_isnan(__type(__f));
}
Run Code Online (Sandbox Code Playgroud)
至少在我看来,这看起来不一定是更好的匹配.
这个问题的动机:
我找到了这些代码行(可能是某些Eclipse自动生成的结果)
using std::isnan
using boost::math::isnan
Run Code Online (Sandbox Code Playgroud)
我想知道为什么编译器不会产生至少一个警告.
当您执行以下操作时,实现必须声明以下重载,或者表现为声明这些重载#include <cmath>:
bool isnan( float arg );
bool isnan( double arg );
bool isnan( long double arg );
bool isnan( Integral arg );
Run Code Online (Sandbox Code Playgroud)
第一个是最好的匹配,所以编译器必须选择它.(对于那些关心的人,N4141中的相关标准为26.8/10.)
请注意,最后一次重载†可能以与模板冲突的方式声明,在这种情况下,using std::isnan;将导致重新声明错误.(这发生在gcc5及更早版本中.)如果这using不会导致错误,则调用很好.
有趣的是,clang确实认为这个电话是模棱两可的.这不应该像我上面解释的那样发生.
我想知道为什么编译器不会产生至少一个警告.
您正在使用该using功能将声明拉入某个范围,这是预期用途.所以我认为没有理由在这里发出警告.然而,我会以这样的方式配置我的编辑器,即不会自动生成这样的using声明,因为这可能会产生令人惊讶的结果.
†我在上面粘贴的字面意义上无法理解这种过载.确切地说,重载代表的是实现定义,它可能是一组重载,一个模板,......它的行为类似于double为所有整数类型转换参数.
| 归档时间: |
|
| 查看次数: |
238 次 |
| 最近记录: |