静默gcc的“仅在-std = c ++ XX或-std = gnu ++ XX时可用”警告

Bar*_*rry 8 c++ g++ c++11 c++17

更高语言版本中的某些语言功能非常有用,并且编译器供应商已选择将它们反向移植到较早版本。最典型的例子是if constexpr

这个简单的程序:

template <typename T>
constexpr int get() {
    if constexpr (sizeof(T) > 10) {
        return 1;
    } else {
        return 0;
    }
}

static_assert(get<int>() == 0, "!");
static_assert(get<char[100]>() == 1, "!");
Run Code Online (Sandbox Code Playgroud)

从技术上讲,按照语言规则需要C ++ 17,并且在C ++ 11中从技术上来说是格式错误的……但是gcc和clang都可以正常编译它-std=c++11。每个发出警告。

Clang告诉您该警告是什么,因此您可以将其禁用:

foo.cxx:3:8: warning: constexpr if is a C++17 extension [-Wc++17-extensions]
    if constexpr (sizeof(T) > 10) {
       ^
1 warning generated.
Run Code Online (Sandbox Code Playgroud)

使用clang进行编译-Wno-C++17-extensions不会产生警告。

但是gcc实际上并没有说出警告的来源:

foo.cxx: In function ‘constexpr int get()’:
foo.cxx:3:8: warning: ‘if constexpr’ only available with -std=c++17 or -std=gnu++17
     if constexpr (sizeof(T) > 10) {
        ^~~~~~~~~
Run Code Online (Sandbox Code Playgroud)

有没有办法关闭此警告?我知道它在C ++ 17上是“仅可用的”,但是有理由不完全使用C ++ 17。

Jon*_*ely 4

正如 Marc 所评论的,在当前 GCC 版本中阻止这些警告的唯一方法是告诉编译器您的代码位于系统标头中。如果代码位于 GCC 标准包含路径(如 )中的标头中/usr/include,则这种情况会自动发生,如果代码位于通过-isystem选项找到的标头中,则这种情况会自动发生。您还可以装饰标头,使 GCC 将其视为系统标头,无论其所在的目录如何,方法如下:

#pragma GCC system_header
Run Code Online (Sandbox Code Playgroud)

如果代码不在头文件中,则无法说它在系统头文件中。任何未#include 的源文件都不会被视为系统标头,无论它位于哪个目录或是否使用#pragma。