2

C__STDC__,但似乎没有识别某些扩展 C++ 方言的标准方法。因此对于我使用的可移植代码

#define __is_extended                                   \
    ((__GNUG__   &&!__STRICT_ANSI__)  ||                \
     (_MSC_VER   && _MSC_EXTENSIONS && __cplusplus)  || \
     (__IBMCPP__ && __EXTENDED__))

到目前为止,这适用于 gcc、XLC 和 Visual C++。

我们必须针对每个编译器测试 ISO/ANSI 一致性,对吗?如果是这样,您能否为其他已被证明有效的编译器提出建议?

编辑:由于对此类测试的赞成和反对进行了很多讨论,因此这是一个真实世界的示例。假设有一些头文件stuff.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 的翻译单元包含stuff.h没有改变。没有编译错误,运行时没有不同的行为。C++11 仍然是实验性的。代码可以安全地提交到主分支,同事可以研究它,从中学习并在其组件中应用技术。

4

3 回答 3

2

Your question is actually backward, because the non-standard extensions supported by a compiler are specific to that compiler - often to the extent of being specific to a particular compiler version - as are the non-standard macros each compiler defines so they can be detected.

The usual technique is the reverse: specify some feature you want, associate it with some macro, and only write code which uses that feature if the associated macro is defined.

Let's say there is some funky feature that is supported - in exactly the same way by Visual C++ 11 and g++ version 3.2.1, but not with any other compilers (not even other versions of Visual C++ or 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

There are plenty of freely available general purpose libraries which use this sort of technique (obviously with better naming of macros). One example that comes to mind is the ACE (Adaptive Communication Environment) framework which has a set of portability macros, documented here.

Using such macros is not a job for the faint-hearted if you are concerned about a large set of non-standard features, given that it is necessary to understand what versions of what compilers (or libraries) support each feature, and to update the macros every time a new compiler, a new library, or even a patch is released.

It is also necessary to avoid using reserved identifiers in naming those macros, and to ensure the macro names are unique. Identifiers starting with a double underscore are reserved.

于 2015-07-19T14:14:56.557 回答
1

一般来说,这很难做到,因为如果您依赖于不符合标准的编译器,那么就没有标准化的方法来只需要标准规则(标准没有指定非标准编译器的行为)。

您可以做的是添加额外的构建步骤或提交挂钩,并通过具有特定严格一致性选项的特定可移植编译器(如 g++)传递代码。

于 2015-07-19T09:58:05.560 回答
0

首先,不允许以这种方式命名变量 ( #define __is_extended),因为以两个下划线开头的名称是为实现保留的。

您拥有的方法仍然依赖于编译器并且可能会失败:除了 之外__cplusplus,这些宏都不是标准的,因此不需要实现来定义它们。此外,该测试基本上是检查正在使用的编译器,而不是是否正在使用某些扩展

我的建议就是不要使用扩展。对它们的需求非常少。如果您仍然想确保它们无论如何都不会被使用,您可以打开编译器的标志来限制扩展的使用;对于 GCC,在"Options Controlling C Dialect"一节中有整整一章的内容。

于 2015-07-19T10:19:00.957 回答