使用宏检测 gcc 而不是 msvc / clang

Detect gcc as opposed to msvc / clang with macro

我正在开发一个项目,到目前为止,它是用 gcc 和 msvc 构建的。我们最近也开始使用 clang 进行构建。

代码中有一些部分完成了特定于平台的事情:

#ifndef _WIN32
// ignore this in msvc
#endif

因为 gcc 以前是唯一的非 windows 构建,这等同于说 "do this only for gcc"。但现在它意味着 "do this only for gcc and clang".

然而,在某些情况下,我想专门为 gcc 处理一些事情,而不是为 clang 处理。有没有一种简单而强大的方法来检测gcc,即

#ifdef ???
// do this *only* for gcc
#endif
__GNUC__
__GNUC_MINOR__
__GNUC_PATCHLEVEL__

These macros are defined by all GNU compilers that use the C preprocessor: C, C++, Objective-C and Fortran. Their values are the major version, minor version, and patch level of the compiler, as integer constants. For example, GCC 3.2.1 will define __GNUC__ to 3, __GNUC_MINOR__ to 2, and __GNUC_PATCHLEVEL__ to 1. These macros are also defined if you invoke the preprocessor directly.

还有:

__GNUG__

The GNU C++ compiler defines this. Testing it is equivalent to testing (__GNUC__ && __cplusplus).

Source

显然,clang 也使用它们。但是它也定义了:

__clang__
__clang_major__
__clang_minor__
__clang_patchlevel__

所以你可以这样做:

#ifdef __GNUC__
    #ifndef __clang__
...

甚至更好(注意顺序):

#if defined(__clang__)
....
#elif defined(__GNUC__) || defined(__GNUG__)
....
#elif defined(_MSC_VER)
....

使用 Boost,这变得非常简单:

#include <boost/predef.h>

#if BOOST_COMP_GNUC
// do this *only* for gcc
#endif

另请参阅 boost 文档的 Using the predefs 部分。

(感谢 rubenvb 在评论中提到了这一点,感谢 Alberto M 添加了包含,感谢 Frederik Aalund 将 #ifdef 更正为 #if

我使用这个定义:

#define GCC_COMPILER (defined(__GNUC__) && !defined(__clang__))

并用它进行测试:

#if GCC_COMPILER
...
#endif