C++ 识别非标准C++;便携式的? c> SysStdc

C++ 识别非标准C++;便携式的? c> SysStdc,c++,c-preprocessor,gnu,ansi,xlc,C++,C Preprocessor,Gnu,Ansi,Xlc,我们必须测试每个编译器的ISO/ANSI符合性,对吗?如果是这样的话,您能为其他被证明有效的编译器提供建议吗 编辑:因为有很多关于这种测试的赞成和反对的讨论,这里有一个真实的例子。假设有一些头文件。h广泛用于多个项目中的多个编译器。stuff.h使用一些特定于编译器的vsnprintf(在C++11之前未标准化),一些copy\u if(在C++98中使用),拥有互斥锁保护等等。在实现干净的C++11变体时,如果扩展了(更好的是:\uu是idosyncratic或!\uu是ANSI\uc11),

我们必须测试每个编译器的ISO/ANSI符合性,对吗?如果是这样的话,您能为其他被证明有效的编译器提供建议吗


编辑:因为有很多关于这种测试的赞成和反对的讨论,这里有一个真实的例子。假设有一些头文件。h广泛用于多个项目中的多个编译器。stuff.h使用一些特定于编译器的
vsnprintf
(在C++11之前未标准化),一些
copy\u if
(在C++98中使用),拥有互斥锁保护等等。在实现干净的C++11变体时,如果扩展了
(更好的是:
\uu是idosyncratic
!\uu是ANSI\uc11
),则将旧的(但受信任的)实现包装在一些
中。新的C++11采用了
#else
。当仍然编译为C++0x或C++98的翻译单元包含stuff.h时,没有任何更改。没有编译错误,运行时没有不同的行为。C++11仍处于实验阶段。代码可以安全地提交到主分支,同事可以研究它,从中学习,并将技术应用到他们的组件中

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


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

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

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


我的建议就是不要使用扩展。几乎不需要它们。如果您仍然想确保它们不会被使用,您可以打开编译器的标志来限制扩展的使用;对于GCC,本节中有一整章都是关于这一点的

您的问题实际上是反向的,因为编译器支持的非标准扩展是特定于该编译器的—通常是特定于特定的编译器版本—每个编译器定义的非标准宏也是如此,因此可以检测到它们

通常的方法是相反的:指定您想要的某个功能,将其与某个宏关联,并且仅在定义了关联宏的情况下编写使用该功能的代码

我们假设有一些时髦的特性,用Visual C++ 11和g++版本3.2.1完全相同,但不是用任何其他编译器(甚至不是VisualC++或g++的其他版本)。 有很多免费提供的通用库使用这种技术(显然宏的命名更好)。我想到的一个例子是,它有一组可移植性宏,并有文档记录

如果您担心大量非标准功能,那么使用此类宏不是胆小鬼的工作,因为有必要了解哪些编译器(或库)支持每个功能的版本,并在每次发布新编译器、新库甚至修补程序时更新宏


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

这样的宏有什么好处?非标准扩展确实因编译器而异,所以您只知道一些扩展被激活。我不理解这个问题。你能给出一个具体的例子,说明你将如何处理
\u扩展后的结果吗?确保某些翻译单元不能使用某些语言扩展。启用编译时断言,如
#if是扩展的#error这是可移植的代码#endif
或宏,如
#define#u是ANSI(cplusplus==201103L&!#u是扩展的)
@anderspindler:但这比简单地用严格的一致性标志调用编译器更好吗?例如,如果使用
/Ze
标志,将定义
\u MSC\u扩展。解决此问题的方法不是使用
/Ze
,而是使用
/Za
。为什么要先在编译器中启用扩展,然后将自己的编译器配置视为错误?定义上述标记会使程序在标准下格式错误。我也看不出你会如何有效地使用它。(1)
\MSC\u扩展
\uu严格的
\uuu扩展的
实际上只有在使用一些扩展时才被定义。(2) 是的-由于C++11,扩展的使用较少。但是有很多C++98代码将被缓慢迁移。(3) 即使是
gcc-Wall-Wextra-pedantic
也不会抱怨带下划线的名字,所以我想我们是安全的:-)@AndreasSpindler 1)它们不需要定义。另外,对于gcc/clang,带有扩展的示例代码没有定义它们<如果指定了
-ANSI
-std
,则代码>\uuuuu STRICT\uANSI\uuuuuu
仅存在。3) 是UB。不需要诊断,编译器可以做任何它想处理的事情。看,我不明白你说的“他们不需要定义”是什么意思。只要手册上说特定的宏是在特定的c语言下定义的
//  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