尽管使用C++ 14功能,为什么使用C++ 11进行编译仍然是成功的?

DBe*_*nko 16 c++ gcc compiler-warnings c++11 c++14

GCC v6.1(结果与v5.1相同)使用flags成功编译了下面的代码-std=c++11 -Wall -Wextra -Wpedantic,但产生了这个警告:

variable templates only available with -std=c++14 or -std=gnu++14
Run Code Online (Sandbox Code Playgroud)

代码:

#include <iostream>

template <typename T>
struct ParamMetadata {
        T min;
        T max;
};

template <class T1, class T2>
class FooMap {};

template <typename T>
// WARNING PRODUCED ON THIS LINE
extern FooMap<int, ParamMetadata<T> > metadataHashmap;

int main() {
        return 0;
}
Run Code Online (Sandbox Code Playgroud)

Clang v3.8产生了类似的警告:

variable templates are a C++14 extension [-Wc++14-extensions]
Run Code Online (Sandbox Code Playgroud)

如果这是仅在C++ 14中可用的功能,为什么用C++ 11标记编译就好了,我可以运行可执行文件?这不应该是一个致命的错误吗?

Yak*_*ont 13

C++标准没有"致命的编译器错误"的概念.程序要么形成错误,要么需要诊断,要么形成不良,不需要诊断或形式良好.

在C++中,标准对错误的程序诊断的唯一要求是显示诊断1.未定义该诊断的内容.除了诊断之外还会发生什么其他事情.

许多编译器实现了C++标准的扩展,他们被告知要编译它们,否则就会产生不正确的程序,并产生可运行的可执行文件.如果它们符合标准,他们唯一必须做的就是打印一条警告信息(满足C++标准的诊断要求).

在这种情况下,它正在打印您使用C++ 14功能的警告消息.它现在已成功完成了C++ 11标准所需的错误程序.它还生成一个可执行程序,它可以执行程序在使用C++ 14标准的功能时所执行的操作:它可以自由执行,因为此时标准对程序执行的操作没有任何限制.格式不正确的C++ 11程序.

如果你不想要这个选项,编译器通常有一个warnings-as-errors标志,以及各种strictpedantic该块扩展标准,他们使用的标志.然后该错误将抑制可执行文件的生成,您将不再感到困惑.

默认情况下,gcc假定您实际上希望将提供的代码编译成某些内容,而不是作为标准实施者,并且只有在没有合理的方法将您的代码解释为可能符合您的意图的程序时才会生成错误.它提供标志以将其切换到严格和迂腐模式.


1有趣的是,打印出单个空格字符可满足显示诊断的要求.可以用病理方式读取C++标准,以便在编译器中生成低质量的实现:生成恶意的编译器证明标准是不值得的.

  • "它还生成一个可执行程序,它执行程序在C++ 14标准下编译时会执行的操作" - 仅针对此特定功能:程序的其他部分仍可使用C +成功编译+11规则在C++ 14中会有所不同. (3认同)