Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/125.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ SFINAE从另一个命名空间测试自由函数_C++_Sfinae - Fatal编程技术网

C++ SFINAE从另一个命名空间测试自由函数

C++ SFINAE从另一个命名空间测试自由函数,c++,sfinae,C++,Sfinae,我试图想出一种方法来测试std::isnan是否是在预处理器中没有特殊的外壳编译器的情况下定义的,并得出了以下结论,我希望它能很好地工作 #include <cmath> #include <type_traits> namespace detail { using namespace std; struct dummy {}; void isnan(dummy); //bool isnan(float); // Just addin

我试图想出一种方法来测试
std::isnan
是否是在预处理器中没有特殊的外壳编译器的情况下定义的,并得出了以下结论,我希望它能很好地工作

#include <cmath>
#include <type_traits>

namespace detail {
    using namespace std;

    struct dummy {};
    void isnan(dummy);

    //bool isnan(float); // Just adding this declaration makes it work!

    template <typename T>
    struct is_isnan_available {
        template <typename T1>
        static decltype(isnan(T1())) test(int);
        template <typename>
        static void test(...);

        enum { value = !std::is_void<decltype(test<T>(0))>::value };
    };
}

int main() {
    return detail::is_isnan_available<float>::value;
}
#包括
#包括
名称空间详细信息{
使用名称空间std;
结构虚拟{};
void isnan(虚拟);
//bool-isnan(float);//只需添加此声明即可工作!
模板
结构是否可用{
模板
静态decltype(isnan(T1()))测试(int);
模板
静态孔隙试验(…);
枚举{value=!std::is_void::value};
};
}
int main(){
返回详细信息::是否可用::值;
}
结果是。我知道某些
std::isnan
是在ideone上定义的,因为我手动测试了它

当我离开的时候,它就起作用了


我错过了什么?是什么解释了这种行为?

问题是,using指令没有将成员添加到当前名称空间,因此
std::
成员仍然可能被该名称空间中的声明隐藏

使用std::isnan
的行为将类似于将导入的命名空间的成员添加到包含
use
-位置和导入的命名空间的命名空间中。using声明是名称空间中的普通声明,因此可以使用后面的声明参与重载解析


但是,正如注释中指出的,如果函数不存在,则会产生错误。来解决你需要解决的问题。这应该行得通,因为导入的定义将与
虚拟
重载处于同一级别。您可以将重载带到全局名称空间,也可以创建一个辅助名称空间(在全局名称空间中)和。

我为一组POSIX线程安全API解决了这个问题,这些API取代了非线程安全的标准函数:。此代码检测是否在全局命名空间中定义了API,如果它不存在,则选择自定义解决方法。

好奇:isnan可用吗::值工作?@Tony:
std::isnan
对这两个API都重载。即使这样,也有一个从float到double的隐式转换。不过,我还是试过了,测试double也不起作用。@TonyDelroy:好主意,不过标准函数通常都是重载的。尽管如此,您仍然可以检查@R.MartinhoFernandes是否仍然不起作用:您可以使用
std::declval()
isnan
提供值——好吧,这里可能有点过头了,完全不相关,但对于类类型很有用(不一定是默认构造函数)@Matthieu:谢谢,我知道这一点,但由于我只对标准浮点类型感兴趣,所以我选择了可读版本:),如果不存在,将导致一个硬错误。我必须使用名称空间
,因为如果我希望函数不存在,我就无法命名该函数。你能解释一下这两者在名称查找方面的区别吗?直觉上我认为
使用名称空间
只是一次导入所有符号的快捷方式,我当然不希望在名称查找方面出现差异。啊,就是这样!我不知道我会用它来隐藏声明。谢谢。啊,谢谢你的区别。我不知道
使用名称空间
注入的符号不是“真正”注入的,因此仍然受到名称隐藏的影响。