Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why compiling with C++11 is successful despite using C++14 feature?

GCC v6.1 (the result is the same with v5.1) successfully compiles the code below with flags -std=c++11 -Wall -Wextra -Wpedantic, but produces this warning:

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

The code:

#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 produces a similar warning:

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

If this is a feature only available in C++14, why does it compile with C++11 flag just fine and I can run the executable? Shouldn't it be a fatal error?

like image 761
DBedrenko Avatar asked Jun 02 '16 09:06

DBedrenko


2 Answers

The C++ standard does not have the concept of a "fatal compiler error". Programs are either ill-formed with a diagnostic required, or ill-formed with no diagnostic required, or well-formed.

In C++, the only requirement the standard places on a ill-formed program diagnostic is to display a diagnostic1. The contents of that diagnostic are not defined. What else happens besides that diagnostic is not defined.

Many compilers implement extensions to the C++ standard they are told to compile against that take otherwise ill-formed programs and produce a runnable executable. If they are compliant to a standard, the only thing they must do is print a warning message (which satisfies the diagnostic requirement of the C++ standard(s)).

In this case, it is printing a warning message that you used a C++14 feature. It has now successfully done what the C++11 standard requires with your ill-formed program. It also produces an executable that does what your program would do if that feature from the C++14 standard was used: it is free to do so, as the standard at this point places no restrictions on what the program does once it is an ill-formed C++11 program.

If you don't want this option, compilers often have a warnings-as-errors flag, and various strict and pedantic flags that block extensions to the standard they use. Then the error will suppress the generation of the executable, and you will no longer be confused.

gcc by default assumes you actually want to compile the provided code into something, rather than act as a standard-enforcer, and only generates errors when it has no reasonable way to interpret your code as a program that probably matches your intentions. It provides flags to switch it to a strict and pedantic mode.


1 Amusingly, printing out a single space character satisfies the requirement to display a diagnostic. The C++ standard can be read in pathological ways in order to generate a poor quality of implementation in your compiler: generating a hostile compiler-proof standard is not worth the effort.

like image 157
Yakk - Adam Nevraumont Avatar answered Nov 10 '22 13:11

Yakk - Adam Nevraumont


Nothing "should be a fatal error". If the compiler writes a message telling you what happened it's fulfilled its obligations.

You are now free to make a fully informed decision about whether to treat the code as having fatal error and change the code; or to treat it as if it were C++14 and go with it.

You can use the switch -Werror (changes the word "warning" to "error" in the message) if you feel it would help.

like image 20
M.M Avatar answered Nov 10 '22 11:11

M.M