严格遵守Visual C++标准
Strict standards-compliance with Visual C++
这个问题与以下任何一个都不一样:
- 将Visual C++Studio/Express设置为严格的ANSI模式
- 当使用Microsoft';的Visual C++编译器
我正在运行Windows 7和Visual Studio Express 2012,但我希望两者都不会影响这个问题的答案。
tl;dr在仍然允许使用Visual C++进行编译的情况下,我该如何最恰当地抵消/防止/容忍以下math.h摘录的影响?
#if !__STDC__
/* Non-ANSI names for compatibility */
#define DOMAIN _DOMAIN
#define SING _SING
#define OVERFLOW _OVERFLOW
#define UNDERFLOW _UNDERFLOW
#define TLOSS _TLOSS
#define PLOSS _PLOSS
#define matherr _matherr
背景:我正在写一个基于文本的C++项目,它的总体目标远远超出了这个问题的范围。我使用GNU Make(为了熟悉和可移植性)用Cygwin g++和cl.exe编译它,并假设有一个严格符合标准的环境。。。目前为止我开始认为Windows根本不允许这样的假设。
我有一个枚举,其成员包括OVERFLOW
和UNDERFLOW
。下面描述的问题可能会迫使我更改这些名称,但我更愿意保留它们,因为它们最适合我的用途,尽管受到Windows头文件等外部影响。
GCC、Visual C++和Mac OS X的头文件(独立于llvm GCC)都默认在math.h中定义OVERFLOW
和UNDERFLOW
以及其他非标准宏。
- GCC有一系列文件化的方法,可以干净地防止这些定义
- MacOSX有几种未记录的方法可以做到这一点,其中一种(
_POSIX_C_SOURCE
)与GCC的文档一致。(我提到这一点是为了弥补苹果公司缺乏文档的缺陷;我有使用这些标识符的历史。) - MSDN记录了/u命令行选项,作为一种防止在Visual C++中定义一些非标准宏的方法(通过
__STDC__
宏)。如本问题开头所示,__STDC__
宏也阻止定义OVERFLOW
和UNDERFLOW
当发现/u开关会阻止我所关心的定义时,我将其添加到我的makefile中。但后来我从crtdfs的第44行得到了一个新的错误。h:
error C1189: Only Win32 target supported!
这是因为不再定义_WIN32
。搜索表明crtdfs.h与Windows驱动程序开发工具包有关。我没有开发驱动程序;我可以不使用那个标题吗?还是我只需要重命名枚举成员以容忍非标准的Windows行为?
不要使用具有多种效果的/u
编译器开关,只需使用/D__STDC__=1
即可定义__STDC__
宏,而不使用其他功能。
脑海中浮现出两种可能性。
第一个是确保在包含math.h
时反转特定效果,比如:
#include <math.h>
#undef OVERFLOW
#undef UNDERFLOW
现在,这也可能会导致一些代码出现问题,这些代码希望这些东西得到正确定义。然而,即使在这种情况下,你也可以修改你的软件,为math.h
使用不同的名称:
#include <math.h>
#undef OVERFLOW
#undef UNDERFLOW
#define MATH_H_OVERFLOW _OVERFLOW
#define MATH_H_UNDERFLOW _UNDERFLOW
您只需要确保所有想要使用math.h
常量的源代码(像库这样已经编译的代码),使用MATH_H_*
常量,而不是枚举中的常量。
第二个是非常仔细地考虑你在这个任务中投入的精力,与简单地将你的enum
成员重命名为不冲突的东西所需的精力相比。我第一次尝试使用Overflow
(而不是OVERFLOW
)进行枚举,因为两者中的信息量仍然完全相同,而且它消除了直接的冲突。
是的,我知道找到一种不涉及这一点的方法是很好的,但你应该从事交付软件的业务,而不是花太多时间处理环境中的小问题:-)
在C++11中,您可以使用作用域枚举:
enum class Flows { Underflow, Overflow };
现在您可以参考Flows:Underflow和Flows:Overflow。
即使在C++98中,也可以使用类来模拟它:
class Flows
{
public:
enum Value { Underflow, Overflow };
};
- 使用CMake检测支持的C++标准
- 如何理解C++标准N3337中的expr.const.cast子句8
- "throw expression code" 1e7 >返回 d 是什么?投掷标准::overflow_error( "too big" ) : d;意味 着?
- 编译标准库类型
- 标准是否使用多余的大括号(例如 T{{{10}}})定义列表初始化?
- 编译器如何在使用SFINAE的函数和标准函数之间确定两者是否可行
- 铸造标准::有没有回到原来的类型
- 标准 N3337 5.2.10 第 7 条中的C++"类型"是什么意思?
- this_thread::sleep_for和计时时钟之间的关系是否由C++11标准指定
- 标准库类型的赋值运算符的引用限定符
- 标准是否严格定义了该程序应该如何编译?
- 如何从Windows应用程序输出到标准?
- 安全到标准:移动会员?
- 如何正确将字符串转换为标准::时间::system_clock::time_point?
- 这是否符合C++标准:双响双响,例如!!(-0.0).
- 标准::变体的赋值运算符
- 捕获标准输出以压缩并使用 CTRL-C 中断会给出损坏的 zip 文件
- 如何在 Mac 上使用 c++17 并行标准库算法?
- 强枚举类型定义:Clang Bug 还是 C++11 标准不确定性?
- 并行标准::复制复杂性