可移植地识别非标准c++
Recognize non-standard C++ portably?
C有__STDC__
,但似乎没有标准的方法来识别一些扩展的c++方言。因此对于可移植代码,我使用
#define __is_extended
((__GNUG__ &&!__STRICT_ANSI__) ||
(_MSC_VER && _MSC_EXTENSIONS && __cplusplus) ||
(__IBMCPP__ && __EXTENDED__))
目前为止gcc, XLC和Visual c++都可以使用。
我们必须测试每个编译器的ISO/ANSI一致性,对吗?如果是这样,您能对其他已被证明有效的编译器提出建议吗?
编辑:既然有这么多关于支持和反对这样的测试的讨论,这里有一个真实世界的例子。假设有一些头文件的东西。h在多个项目的多个编译器中广泛使用。stuff.h使用一些编译器特定的vsnprintf
(在c++ 11之前没有标准化),一些copy_if<>
(在c++ 98中不知怎么错过了),自己的互斥锁保护等等。在实现一个干净的c++ 11变体时,您将旧的(但可信的)实现包装在一些#if __is_extended
中(更好的是:__is_idosyncratic
或!__is_ANSI_C11
)。新的c++ 11在#else
之后。当翻译单元仍然编译为c++ 0x或c++ 98时,包含的东西。h没有任何变化。没有编译错误,运行时没有不同的行为。c++ 11仍然是实验性的。代码可以安全地提交给主分支,同事可以研究它,从中学习并将技术应用于他们的组件。
你的问题实际上是向后的,因为编译器支持的非标准扩展是特定于该编译器的-通常是特定于特定编译器版本的程度-每个编译器定义的非标准宏也是如此,因此它们可以被检测到。
通常的技术是相反的:指定一些你想要的特性,将其与一些宏关联,并且只有在关联的宏被定义的情况下才编写使用该特性的代码。
让我们假设有一些时髦的特性被支持-以完全相同的方式被Visual c++ 11和g++版本3.2.1支持,但不支持任何其他编译器(甚至不支持其他版本的Visual c++或g++)。
// in some header that detects if the compiler supports all sorts of features
#if ((defined(__GNUG__) && __GNUC__ == 3 && __GNUC_MINOR__ == 2 && __GNUC_PATCHLEVEL__ == 1) || (defined(_MSC_VER) && _MSC_VER == 1700))
#define FUNKY_FEATURE
#endif
// and, in subsequent user code ....
#ifdef FUNKY_FEATURE
// code which uses that funky feature
#endif
有很多免费的通用库使用了这种技术(显然宏的命名更好)。我想到的一个例子是ACE(自适应通信环境)框架,它有一组可移植性宏,在这里有文档。
如果你关心大量的非标准特性,使用这样的宏不是胆小的人的工作,因为有必要了解哪些版本的编译器(或库)支持每个特性,并在每次发布新的编译器、新的库甚至补丁时更新宏。
还必须避免在命名这些宏时使用保留标识符,并确保宏名称是唯一的。以双下划线开头的标识符是保留的。
一般来说,这很难做到,因为如果你依赖于一个不符合标准的编译器,那么就没有标准化的方法来只要求标准规则(标准没有指定非标准编译器的行为)。
你可以做的是添加一个额外的构建步骤或提交挂钩,并通过特定的可移植编译器(如g++)传递代码,并提供特定的严格一致性选项。
首先,不允许以这种方式(#define __is_extended
)命名变量,因为以两个下划线开头的名称是为实现保留的。
您拥有的方法仍然依赖于编译器,并且可能失败:除了__cplusplus
之外,这些宏都不是标准的,因此实现不需要定义它们。此外,该测试基本上是检查正在使用的编译器,而不是是否使用了一些扩展。
我的建议就是不要使用扩展。对它们的需求非常非常少。如果你仍然想确保它们不会被使用,你可以改变编译器的标志来限制扩展的使用;对于GCC,在"选项控制C方言"一节中有一整章的内容。
- C4204:使用的非标准扩展:非常量聚合初始值设定项
- 在双重继承的情况下如何处理非标准构造函数
- CMake 不编译具有非标准扩展名的文件
- 定义具有非标准签名的自定义映射比较器
- 我想获取点的属性,它报告错误 C3867:"point::output_x":非标准语法;使用"&"创建指向成员的指针
- 非标准语法,使用 & 创建指向成员的指针
- 在Qt中链接具有非标准名称的lib文件
- 非标准语法使用 '&' 创建指向成员 C++ 的指针
- WINAPI EnumWindowsProc:非标准语法;使用 & 创建指向成员的点
- Vulkan-hpp 是reinterpret_casting非标准布局类到另一个类.这合法吗?
- 'cv::Mat::type':非标准语法;使用 '&' 创建指向成员的指针
- registerPointPickingCallback (PCLViewer::callback_Test,(void*)&viewer);返回 C3687 非标准语法;使用"&"创建指向成员的指针
- 错误 C4839:非标准地使用类 'ATL::CW2AEX<520>' 作为可变参数函数的参数
- C++ Visual Studio 2015:非标准语法;使用 '&' 创建指向成员的指针
- 非标准语法;使用 & 创建指向成员的指针
- Visual Studio 2015"非标准语法;使用"&"为成员创建指针"
- 如何将 Boost 库与 CMake 链接(如果 boost 位于非标准位置,则在集群上)?
- Cmake在非标准路径中找到OpenSSL库
- 非标准语法;使用 '&' 创建指向成员的指针错误,将成员函数分配给向量时出错
- GLFW 非标准语法;使用 '&' 创建指向成员的指针