可移植地识别非标准C ++?

时间:2015-07-19 09:45:47

标签: c++ c-preprocessor gnu ansi xlc

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<>they somehow missed在C ++ 98中),拥有互联网守卫,什么不是。在实现干净的C ++ 11变体时,您将旧的(但可信的)实现包装在某些#if __is_extended中(更好:__is_idosyncratic!__is_ANSI_C11)。新的C ++ 11落后于#else。当仍然编译为C ++ 0x或C ++ 98的翻译单元包含 stuff.h 时,没有任何改变。没有编译错误,在运行时没有不同的行为。 C ++ 11仍然是实验性的。代码可以安全地提交给主分支,同事可以研究它,从中学习并使用其组件应用技术。

3 个答案:

答案 0 :(得分:2)

您的问题实际上是向后的,因为编译器支持的非标准扩展特定于该编译器 - 通常是特定于特定编译器版本的程度 - 每个编译器定义的非标准宏也是如此可以被发现。

通常的技术是相反的:指定您想要的某些功能,将其与某个宏关联,并且只有在定义了相关宏的情况下才编写使用该功能的代码。

让我们说有一些时髦的功能得到支持 - 以完全相同的方式被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 (Adaptive Communication Environment) framework,它有一组可移植性宏,记录在案here

如果您关注大量非标准功能,那么使用这些宏并不适合胆小的人,因为有必要了解哪些编译器(或库)支持每个功能的版本,以及每次发布新编译器,新库甚至补丁时都要更新宏。

还必须避免在命名这些宏时使用保留标识符,并确保宏名称是唯一的。以双下划线开头的标识符将被保留。

答案 1 :(得分:1)

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

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

答案 2 :(得分:0)

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

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

我的建议是不要使用扩展程序。对他们的需求非常小。如果你仍然想确保它们不被使用,你可以转动你的编译器标志来限制扩展的使用;对于GCC,在"Options Controlling C Dialect"部分中有关于此的整章。