为什么这个对isnan的调用不含糊?aka关键字使用引入2次类似的函数声明

Ant*_*nio 4 c++ namespaces

以下代码编译并生成一个调用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)

我想知道为什么编译器不会产生至少一个警告.

Bau*_*gen 5

当您执行以下操作时,实现必须声明以下重载,或者表现为声明这些重载#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为所有整数类型转换参数.