# Determining the compiler default C++ standard

**URL:** https://discourse.cmake.org/t/determining-the-compiler-default-c-standard/10389
**Category:** Usage
**Created:** [March 18, 2024, 10:41am UTC](https://discourse.cmake.org/t/determining-the-compiler-default-c-standard/10389 "2024-03-18T10:41:45Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![adaldev](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/a/9dc877/32.png) [@adaldev](https://discourse.cmake.org/u/adaldev)
#### Post date: [March 18, 2024, 10:41am UTC](https://discourse.cmake.org/t/determining-the-compiler-default-c-standard/10389/1 "2024-03-18T10:41:45Z")

</div>

Hi,

This question is related to [setting c++ standard from target\_compile\_option goes for higher standard - #8 by adaldev](https://discourse.cmake.org/t/setting-c-standard-from-target-compile-option-goes-for-higher-standard/10147/8).

Investigating on the question of the actual C++ dialect used when requesting on with `target_compile_features` I discovered that my CMake version set 2 variables:

```cmake
CMAKE_CXX_STANDARD_COMPUTED_DEFAULT
CMAKE_CXX_STANDARD_DEFAULT

```

They actually seemed to correspond to the requested compiler default standard and CMake behavior seems to replace my `target_compile_features` request by the compiler default if this one is higher than my demand.

The reason why has been discussed in the provided link but now I’m wondering if these variable can be safely used to deduce and report the actual version used (which does not appear in any other variable). AFAIK, they are not cached variables, and no cached variable contains the desired information either.

Regards,  
A.

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [April 10, 2024, 11:17pm UTC](https://discourse.cmake.org/t/determining-the-compiler-default-c-standard/10389/2 "2024-04-10T23:17:51Z")

</div>

As I said there, it’s a generator-time determination of what the actual standard in use is. The only 100% reliable way to detect any of this is with the `__cplusplus` preprocessor symbol.

---

<div class="post-metadata">

### Author: ![adaldev](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/a/9dc877/32.png) [@adaldev](https://discourse.cmake.org/u/adaldev)
#### Post date: [April 11, 2024, 7:57am UTC](https://discourse.cmake.org/t/determining-the-compiler-default-c-standard/10389/3 "2024-04-11T07:57:29Z")

</div>

Thanks,

I’d like to be sure to understand.  
`CMAKE_CXX_STANDARD_DEFAULT` is set at configuration time but actual standard used (for instance through an added `-std` option) is determined at generation time?

Is there a rule that, if user is requesting some standard, the chosen option at generation time is the greater of the user-requested and the `CMAKE_CXX_STANDARD_DEFAULT`?  
Is it a behavior that can change in time or that depends on the generator?

IMHO, it’s a “bug” that this behavior is not explicitly documented (but, as discussed in another thread, maybe I’m over-zealous and the only thing that matters for coder is to have, at least, the requested standard).

Regards  
PS though C++ tries to be legacy-compliant it’s not always the case. I’ve got code that broke because some functions became constexpr and it changed some specialization choices in library using metaprogramming, leading to wrong behavior.  
It took me time to track down the issue and, in the meantime, it was a real issue to have my builds updated to C++17, while only C++14 was working.

---

<div class="post-metadata">

### Author: ![scivision](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/s/a87d85/32.png) [@scivision](https://discourse.cmake.org/u/scivision)
#### Post date: [April 11, 2024, 12:09pm UTC](https://discourse.cmake.org/t/determining-the-compiler-default-c-standard/10389/4 "2024-04-11T12:09:39Z")

</div>

There was yet another thread where enforcing a C++ maximum version within the ,cpp source files was discussed.

```cpp
#if __cplusplus > 
#error 
#endif

```

Another way to do this might be to check each target property cxx\_standard If the source C++ files cannot be modified due to management decision.

Another way would be to have cmake generate and then a separate checker script parse compile\_commands.json. although that does not account for the default C++ standard of particular compiler versions.

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [April 11, 2024, 3:36pm UTC](https://discourse.cmake.org/t/determining-the-compiler-default-c-standard/10389/5 "2024-04-11T15:36:46Z")

</div>

> [@adaldev](#):
>
> IMHO, it’s a “bug” that this behavior is not explicitly documented

Hmm, I could not find where the merge logic of “use newest compile feature” is documented. @brad.king? We could use a few extra cross-references to where it does (will?) live from `COMPILE_FEATURES`, `target_compile_features`, and the `<LANG>_STANDARD` variable docs.

---

<div class="post-metadata">

### Author: ![brad.king](https://discourse.cmake.org/user_avatar/discourse.cmake.org/brad.king/32/11_2.png) [@brad.king](https://discourse.cmake.org/u/brad.king)
#### Post date: [April 11, 2024, 3:54pm UTC](https://discourse.cmake.org/t/determining-the-compiler-default-c-standard/10389/6 "2024-04-11T15:54:54Z")

</div>

`CMAKE_CXX_STANDARD[_COMPUTED]_DEFAULT` are implementation details that are not documented or meant for public use.

> where the merge logic of “use newest compile feature” is documented

I don’t think we document any specific algorithm for selecting a standard level. The [documentation of each `cxx_std_##`](https://cmake.org/cmake/help/v3.29/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.html#high-level-meta-features-indicating-c-standard-support) feature says it means only that the “Compiler mode is at least C++##”. That document also says “If the compiler’s default standard level is at least that of the requested feature, CMake may omit the `-std=` flag.”

---

<div class="post-metadata">

### Author: ![adaldev](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/a/9dc877/32.png) [@adaldev](https://discourse.cmake.org/u/adaldev)
#### Post date: [April 11, 2024, 4:12pm UTC](https://discourse.cmake.org/t/determining-the-compiler-default-c-standard/10389/7 "2024-04-11T16:12:11Z")

</div>

Thanks for all the details.

I note also that I should not use `CMAKE_CXX_STANDARD[_COMPUTED]_DEFAULT`.

Thus it leaves me with my issue where I needed (at least temporarily) an exact C++ dialect. Do you feel it can be a motivation for opening an issue (feature request)?

Regards

---

<div class="post-metadata">

### Author: ![brad.king](https://discourse.cmake.org/user_avatar/discourse.cmake.org/brad.king/32/11_2.png) [@brad.king](https://discourse.cmake.org/u/brad.king)
#### Post date: [April 11, 2024, 4:30pm UTC](https://discourse.cmake.org/t/determining-the-compiler-default-c-standard/10389/8 "2024-04-11T16:30:28Z")

</div>

> [@adaldev](#):
>
> my issue where I needed (at least temporarily) an exact C++ dialect

Use [CMAKE\_CXX\_STANDARD](https://cmake.org/cmake/help/v3.29/variable/CMAKE_CXX_STANDARD.html)/[CXX\_STANDARD](https://cmake.org/cmake/help/v3.29/prop_tgt/CXX_STANDARD.html) and [CMAKE\_CXX\_STANDARD\_REQUIRED](https://cmake.org/cmake/help/v3.29/variable/CMAKE_CXX_STANDARD_REQUIRED.html)/[CXX\_STANDARD\_REQUIRED](https://cmake.org/cmake/help/v3.29/prop_tgt/CXX_STANDARD_REQUIRED.html) for that. The specified stanard should be used unless some feature passed to `target_compile_features` requires a higher one.

---

<div class="post-metadata">

### Author: ![craig.scott](https://discourse.cmake.org/user_avatar/discourse.cmake.org/craig.scott/32/20_2.png) [@craig.scott](https://discourse.cmake.org/u/craig.scott)
#### Post date: [April 11, 2024, 10:57pm UTC](https://discourse.cmake.org/t/determining-the-compiler-default-c-standard/10389/9 "2024-04-11T22:57:01Z")

</div>

I thought even `CXX_STANDARD` still ended up being part of the same logic that ensured that at least that version was used, not that it should use that exact version. In other words, I don’t think `CXX_STANDARD` guarantees you’ll get that exact standard either, even if there are no `target_compile_features()` that ask for something higher. But I haven’t checked the code lately to reconfirm my understanding (it’s been a while since I’ve looked at that logic).

---

<div class="post-metadata">

### Author: ![brad.king](https://discourse.cmake.org/user_avatar/discourse.cmake.org/brad.king/32/11_2.png) [@brad.king](https://discourse.cmake.org/u/brad.king)
#### Post date: [April 12, 2024, 12:59pm UTC](https://discourse.cmake.org/t/determining-the-compiler-default-c-standard/10389/10 "2024-04-12T12:59:45Z")

</div>

The `cxx_std_##` features are for minimum standard levels. `CXX_STANDARD` will be honored even if it is lower than the compiler’s default, and an explicit `-std=` flag will be used to achieve it if necessary.

---

<div class="post-metadata">

### Author: ![adaldev](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/a/9dc877/32.png) [@adaldev](https://discourse.cmake.org/u/adaldev)
#### Post date: [April 22, 2024, 8:04am UTC](https://discourse.cmake.org/t/determining-the-compiler-default-c-standard/10389/11 "2024-04-22T08:04:18Z")

</div>

Hi,

I’ve just made a test. I’ve replaced

```cmake
target_compile_features(${TARGET_NAME} PUBLIC cxx_std_14)

```

by

```cmake
set(CXX_STANDARD C++14)

```

I’ve cleaned the cache and in both cases, `-std=c++17` is added to my gcc command line.

Regards  
A.

---

<div class="post-metadata">

### Author: ![brad.king](https://discourse.cmake.org/user_avatar/discourse.cmake.org/brad.king/32/11_2.png) [@brad.king](https://discourse.cmake.org/u/brad.king)
#### Post date: [April 22, 2024, 12:57pm UTC](https://discourse.cmake.org/t/determining-the-compiler-default-c-standard/10389/12 "2024-04-22T12:57:46Z")

</div>

> [@adaldev](#):
>
> `set(CXX_STANDARD C++14)`

Unless the project code does something with that, it is not meaningful to CMake. To request C++14 via the property/variable use either:

```cmake
set_property(TARGET ${TARGET_NAME} PROPERTY CXX_STANDARD 14)

```

after creating the target, or

```auto
set(CMAKE_CXX_STANDARD 14)

```

before creating the target.

---

<div class="post-metadata">

### Author: ![adaldev](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/a/9dc877/32.png) [@adaldev](https://discourse.cmake.org/u/adaldev)
#### Post date: [April 22, 2024, 1:56pm UTC](https://discourse.cmake.org/t/determining-the-compiler-default-c-standard/10389/13 "2024-04-22T13:56:40Z")

</div>

My bad. This way it seems to work.

In order to sum up the thread:

- there’s no “official” way to check the standard that will be actually chosen when using `target_compile_features`
- you can force a standard with `set_property(TARGET ${TARGET_NAME} PROPERTY CXX_STANDARD <value>)`

Thanks again, regards  
PS I’ll mark this comment as answer as it is merging all the provided information

---

<div class="post-metadata">

### Author: ![redbaron](https://discourse.cmake.org/user_avatar/discourse.cmake.org/redbaron/32/2129_2.png) [@redbaron](https://discourse.cmake.org/u/redbaron)
#### Post date: [September 30, 2024, 9:11am UTC](https://discourse.cmake.org/t/determining-the-compiler-default-c-standard/10389/14 "2024-09-30T09:11:39Z")

</div>

Is `CMAKE_CXX_STANDARD` forcing flag a policy-enabled behavior? I can’t make it work when building protobuf. I don’t have minimal reproducer yet, but here are pieces I have found so far:

MSVC compiler’s `CMakeCXXCompiler.cmake` has:

```auto
set(CMAKE_CXX_STANDARD_COMPUTED_DEFAULT "14")
set(CMAKE_CXX_EXTENSIONS_COMPUTED_DEFAULT "OFF")

```

configure is called with `-DCMAKE_CXX_STANDARD=14` and `CMakeCache.txt` contains following:

```auto
CMAKE_CXX_STANDARD:UNINITIALIZED=14

```

target configuration has following snippet:

```auto
    target_compile_features("${target}" PUBLIC cxx_std_14)

```

and unless I change it to `cxx_std_17` I see no `/std:c++14` flags passed to `cl.exe`

My CMake is `3.30.3`, but project CMakeLists.txt is `cmake_minimum_required(VERSION 3.10...3.26)`.

---

<div class="post-metadata">

### Author: ![redbaron](https://discourse.cmake.org/user_avatar/discourse.cmake.org/redbaron/32/2129_2.png) [@redbaron](https://discourse.cmake.org/u/redbaron)
#### Post date: [September 30, 2024, 9:34am UTC](https://discourse.cmake.org/t/determining-the-compiler-default-c-standard/10389/15 "2024-09-30T09:34:56Z")

</div>

Done few more experiments:

1. remove `cxx_std_14` + `CMAKE_CXX_STANDARD=14`: NO FLAG
2. remove `cxx_std_14` + `CMAKE_CXX_STANDARD=17`: flag `/std:c++17` is added
3. keep `cxx_std_14` + `CMAKE_CXX_STANDARD=17`: flag `/std:c++17` is added
4. (as mentioned in post) updating to `cxx_std_17` and not passing `CMAKE_CXX_STANDARD`: flag `/std:c++17` is passed

It seems there is no way to build with `/std:c++14` if compiler detected `STANDARD_COMPUTED_DEFAULT=14` :-/

maybe important: target depends on imported target which has following:

```auto
set_target_properties(absl::core_headers PROPERTIES
  INTERFACE_COMPILE_FEATURES "cxx_std_14"

```

---

<div class="post-metadata">

### Author: ![brad.king](https://discourse.cmake.org/user_avatar/discourse.cmake.org/brad.king/32/11_2.png) [@brad.king](https://discourse.cmake.org/u/brad.king)
#### Post date: [September 30, 2024, 1:05pm UTC](https://discourse.cmake.org/t/determining-the-compiler-default-c-standard/10389/16 "2024-09-30T13:05:44Z")

</div>

> [@redbaron](#):
>
> unless I change it to `cxx_std_17` I see no `/std:c++14` flags passed to `cl.exe`

`cl` does not model standards below C++14, so it requires no flag to satisfy `CMAKE_CXX_STANDARD=14` or `cxx_std_14`.

---

<div class="post-metadata">

### Author: ![redbaron](https://discourse.cmake.org/user_avatar/discourse.cmake.org/redbaron/32/2129_2.png) [@redbaron](https://discourse.cmake.org/u/redbaron)
#### Post date: [September 30, 2024, 3:25pm UTC](https://discourse.cmake.org/t/determining-the-compiler-default-c-standard/10389/17 "2024-09-30T15:25:06Z")

</div>

I have a problem with third-party vendor toolchain where CMake incorrectly detects (probably self-reported by toolchain/compiler) C+14 as default standard and as a result some code can’t be compiled: it would if -std=C+14 was passed, but it didn’t get passed.

I started to experiment with CMAKE\_CXX\_STANDARD on MSVC as it is something I can potentially build reproducer with to report here.

Reading this thread, I had an impression that `CMAKE_CXX_STANDARD=14` property should force adding `std=c++14` flag even if compiler’s default standard is C++14, but it seems I misunderstood.

Looks like my only option is to either force C++17 or fix compiler detection.

---

<div class="post-metadata">

### Author: ![adaldev](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/a/9dc877/32.png) [@adaldev](https://discourse.cmake.org/u/adaldev)
#### Post date: [September 30, 2024, 3:49pm UTC](https://discourse.cmake.org/t/determining-the-compiler-default-c-standard/10389/18 "2024-09-30T15:49:05Z")

</div>

As mentioned above, did you try `set_property(TARGET ${TARGET_NAME} PROPERTY CXX_STANDARD <value>)` to force C++ standard?

A.

---

<div class="post-metadata">

### Author: ![redbaron](https://discourse.cmake.org/user_avatar/discourse.cmake.org/redbaron/32/2129_2.png) [@redbaron](https://discourse.cmake.org/u/redbaron)
#### Post date: [September 30, 2024, 7:38pm UTC](https://discourse.cmake.org/t/determining-the-compiler-default-c-standard/10389/19 "2024-09-30T19:38:04Z")

</div>

I did try `cmake -DCMAKE_CXX_STANDARD=14` which adds `CXX_STANDARD` property to all non-imported targets. Do you have reason to believe that explicit property will have different effect?

---

<div class="post-metadata">

### Author: ![adaldev](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/a/9dc877/32.png) [@adaldev](https://discourse.cmake.org/u/adaldev)
#### Post date: [October 1, 2024, 9:00am UTC](https://discourse.cmake.org/t/determining-the-compiler-default-c-standard/10389/20 "2024-10-01T09:00:09Z")

</div>

From here:

> [@Determining the compiler default C++ standard](https://discourse.cmake.org/t/determining-the-compiler-default-c-standard/10389/12):
>
> Unless the project code does something with that, it is not meaningful to CMake. To request C++14 via the property/variable use either: set\_property(TARGET ${TARGET\_NAME} PROPERTY CXX\_STANDARD 14) after creating the target, or set(CMAKE\_CXX\_STANDARD 14) before creating the target.

[Next page](https://discourse.cmake.org/t/determining-the-compiler-default-c-standard/10389.md?page=2)
