Why is C++14 mode satisfied with -std=c++1y?

Hi,

I’m just getting started with CMake and have come upon a corner case related to C++14 support with older compilers.

My target platform (RHEL 7) ships with G++ 4.8.5, which does not support C++14 completely. It provides the -std=c++11 option for C++11 support, and the -std=c++1y option for “The next revision of the ISO C++ standard, tentatively planned for 2017. Support is highly experimental, and will almost certainly change in incompatible ways in future releases.”.

But -std=c++1y does not enable full C++14 support with this compiler. For example, using digit separator like int oneMillion = 1'000'000; is not supported by G++ 4.8.5 in any mode. But that feature is part of C++14 standard.

I’ve used these lines in my CMakeLists.txt file:

set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_CXX_EXTENSIONS FALSE) # just to get c++1y instead of gnu++1y - it doesn't affect the actual problem

CMake does not throw any error when using this file with G++ 4.8.5; it simply call g++ with -std=c++1y option. And then at compile time g++ will throw an error because it does not support that digit separator syntax.

How can I get CMake to require a C++14 compatible compiler version instead? I have the DevToolSet7 compiler installed (G++ 7.3.1) alongside, and I want to make sure that CMake throws an error if I accidentally use the old system compiler instead.

I’ve noticed that I can explicitly require this particular C++ feature by adding the line target_compile_features(Tutorial PRIVATE cxx_digit_separators). But I think it somewhat makes the set(CMAKE_CXX_STANDARD 14) line useless if I also have to explicitly specify all the features I expect from C++14 standard?

Thanks in advance for your help,
Oliver

PS: I’ve used CMake 3.7.1, but also tried CMake 3.17.3, and this behavior occurs with both versions.

@robert.maynard

I think CMake’s C++ standard support for old compilers is “best effort”. I don’t think there’s a mechanism to require “full” support because “full” support rarely exists (or pushes compiler requirements way higher). This might be a feature request, though I don’t know how complicated it makes the lookup tables for this.

This is correct.

The CMAKE_CXX_STANDARD levels are populated based on if a compiler has any level of support for that language level. We don’t record full conformance, as that is a never ending argument of defining full conformance ( example MSVC wouldn’t ever be considered to support >= c++11 due to pre-processor conformance ).

Oliver,

Arguably, rather than specifying a standard (conformance is generally limited, except for new compilers and old standards), one might argue that you should specify the features you want, and let CMake figure out the appropriate compilation flags.

I have a very similar situation to yours, except I was more aggressive and chose to go with C++17. And GCC 7.3 support for C++17 is … limited.

In practice, explicitly enumerating a bunch of language features just isn’t practical, because there are so many and no one has them memorized. That’s why the standards are convenient short-hand. But if you have a case where you need a feature and someone tried to compile with a lacking compiler, I wouldn’t hesitate to add the requirement to the CMakeLists.txt file.

Makes sense, I understand the reason for this behavior now. So I will probably stay with set(CMAKE_CXX_STANDARD 14) and add target_compile_features() lines for selected features if the problem comes up.

Thanks for your help!
Oliver