Visual Studio中SFINAE示例代码触发C4530警告的原因咨询
问题:Visual Studio下SFINAE代码触发C4530警告,g++无此问题
我写了一段学习SFINAE的代码,在Visual Studio编译时会触发警告,但用g++编译完全正常。
代码如下:
#include <iostream> #include <type_traits> template <class T, typename std::enable_if<std::is_integral<T>::value, nullptr_t>::type = nullptr> void f(T t) { std::cout << "Integer" << std::endl; return; } template <class T, typename std::enable_if<!std::is_integral<T>::value, nullptr_t>::type = nullptr> void f(T t) { std::cout << "not integer" << std::endl; return; } int main() { f(10); f(5.5); f("Hello"); return 0; }
触发的警告信息:
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30037\include\ostream(746): warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc sfinae2.cpp(9): note: see reference to function template instantiation 'std::basic_ostream<char,std::char_traits<char>> &std::operator <<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,const char *)' being compiled sfinae2.cpp(23): note: see reference to function template instantiation 'void f<int,nullptr>(T)' being compiled with [ T=int ]
添加/EHsc编译选项或者删除函数里的cout语句后,警告就消失了。我想知道为什么必须用这个编译选项。
解答
1. 什么是/EHsc
这是Visual Studio专属的编译选项,用来启用符合C++标准的异常处理语义,各部分含义:
E:开启基础异常处理支持H:保证异常抛出时,栈上的C++对象会被正确销毁(即unwind语义,也就是异常展开时的资源清理逻辑)sc:仅处理C++标准异常,忽略系统级的结构化异常(比如Windows SEH异常)
2. 代码触发警告的原因
你代码里用到的std::cout属于C标准库组件,其内部实现依赖了C异常处理机制(比如流操作失败时可能抛出异常,或者代码中隐含了try/catch结构)。当Visual Studio默认编译选项未开启/EHsc时,编译器检测到代码引用了需要unwind语义支持的组件,但当前编译环境未启用该特性,于是抛出C4530警告——它担心如果发生异常,栈上的对象无法被正确销毁,进而导致资源泄漏或程序状态异常。
3. 为什么g++没有警告
g默认就启用了C异常处理(对应编译选项-fexceptions,默认开启),不需要额外指定选项,因此不会触发类似警告。
4. 删除cout后警告消失的原因
去掉cout语句后,代码不再引用那些内部使用异常处理的标准库组件,编译器检测不到需要unwind语义的场景,自然就不会弹出警告了。
内容的提问来源于stack exchange,提问作者Patricio Loncomilla
相关产品推荐
相关产品推荐

