c++ - 尽管使用了 C++14 功能,为什么使用 C++11 编译成功?

标签 c++ c++11 gcc c++14 compiler-warnings

GCC v6.1(结果与 v5.1 相同)成功编译下面带有标志 -std=c++11 -Wall -Wextra -Wpedantic 的代码,但产生此警告:

variable templates only available with -std=c++14 or -std=gnu++14

代码:

#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;
}

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

variable templates are a C++14 extension [-Wc++14-extensions]

如果这是仅在 C++14 中可用的功能,为什么它可以使用 C++11 标志编译并且我可以运行可执行文件?不应该是 fatal error 吗?

最佳答案

C++ 标准没有“致命编译器错误”的概念。程序要么是不规范的需要诊断,要么是不规范的不需要诊断,或者是规范的。

在 C++ 中,标准对格式错误的程序诊断的唯一要求是显示诊断1。该诊断的内容未定义。除了没有定义诊断之外还会发生什么。

许多编译器实现了对 C++ 标准的扩展,他们被告知要针对这些标准进行编译,否则会采用格式错误的程序并生成可运行的可执行文件。如果他们符合标准,他们唯一要做的就是打印一条警告消息(满足 C++ 标准的诊断要求)。

在这种情况下,它会打印一条警告消息,说明您使用了 C++14 功能。它现在已经成功地完成了 C++11 标准对格式错误的程序的要求。如果使用 C++14 标准中的该功能,它还会生成一个可执行文件,该可执行文件执行您的程序将执行的操作:它是免费的,因为此时标准对程序执行的操作没有任何限制。格式错误的 C++11 程序。

如果你不想要这个选项,编译器通常有一个 warnings-as-errors 标志,以及各种 strictpedantic 标志阻止对他们使用的标准的扩展。那么这个错误就会抑制可执行文件的生成,你就不会再迷茫了。

默认情况下,gcc 假定您确实想将提供的代码编译成某种东西,而不是充当标准执行者,并且仅当它没有合理的方式将您的代码解释为可能符合您意图的程序时才会产生错误。它提供了将其切换到严格和迂腐模式的标志。


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

关于c++ - 尽管使用了 C++14 功能,为什么使用 C++11 编译成功?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37587318/

相关文章:

c++ - 在成员初始化列表中填充 std::array

c++ - Armadillo 与 Boost Odeint : Odeint resizes the state vector to zero during integration 冲突

c++ - 没有辅助变量的 std::vector 中的 Pushing_back 值

c - make - 删除未使用的文件

c++ - 在 C++ 中初始化 std::ofstream 的 vector

c++ - 为什么以下两个程序会产生不同的输出? (C++,位操作,VS 2012)

c++ - 未定义对 `__gxx_personality_sj0` 的引用

c++ - 为什么 GCC 为 0.0/0.0 产生 -nan 和 clang 和 intel 产生 +nan?

c++ - 如何一起使用两个参数包?

C++ STD find_last_of 不工作?