What do the values of the C++ "feature test macros" mean?
Asked Answered
H

2

7

To test for a feature, cppreference mentions these feature test macros: link.

If the feature is present in the compiler, the macro is defined. But I don't understand why, if defined, they are defined to something like 201606, which I believe is a version of C++, not of the compiler.

For example, I am using a very recent version of GCC with -std=c++17 for the feature __cpp_lib_hardware_interference_size. The macro is undefined, which I take to mean GCC doesn't have the feature, despite trying 8.2.1 with the c++17 (and c++2a) switch. In this case, what is the significance of the documented value:

__cpp_lib_hardware_interference_size 201703

(inside the cppreference link)?

Hitt answered 10/10, 2018 at 21:8 Comment(2)
It seems to me It's just future-proofing so that if a feature is deemed incomplete and in need of an update in future versions of the standard, a distinction can be made between pre and post update.Rasla
Also, FYI, it is a version of C++ (not a version of the compiler) because the features are part of the C++ standard, so any compiler compliant to version X of C++ will have those features. I.e. feature support is dependent on the C++ version, not the compiler version (sure, the compiler version tends to increase as it adds support, but the language version is the real key).Ballard
P
10

Based on cppreference.com, it says:

The following macros expand to a numeric value corresponding to the year and month when the feature has been included in the working draft.

When a feature changes significantly, the macro will be updated accordingly.

So, you can check if the feature exists checking if the macro is defined. Or you can check for the feature version based on the macro value.

Pantheas answered 10/10, 2018 at 21:21 Comment(0)
E
-1

I agree with you that feature_test is described as not in the best way. In these cases, it's better to use Languages Standards. They are not publicly available for free, but there are working drafts:

  • [1] Draft of C++2017. Document Number: N4659 / Date: 2017-03-21 / Revises: N4640. link

  • [2] Draft of C++2020. Document Number: N4861 / Date: 2020-04-01 /Revises: N4849. link

(Links with draft can be out of date after 10 years, but I have provided the names of the documents to not violate StackOverflow policy.)


For example, I am using a very recent version of GCC with -std=c++17 for the feature __cpp_lib_hardware_interference_size. The macro is undefined, which I take to mean GCC doesn't have the feature...

Not exactly. Let's be careful. This inline constexpr constant is available from C++2017 hardware_destructive_interference_size, but the problem is that feature_test feature_test abilities with __cpp_* has been introduced only in C++2020. You will not find any of __cpp_* Marcoses in [1]. What is not supported is not a feature in C++2017 from GCC Toolchain, but the ability to test a feature with feature test macros by itself.

To test for a feature, cppreference mentions these feature test macros...

You can test the feature if feature testing is supported. And it is supported only from C++2020 (officially).

In all versions of C/C++, the compiler reserved the following names:

  • Starting with a double underscore __
  • Names that start with a single underscore _ followed by an uppercase letter.

You can try to use this mechanism in C++98/03/11/14/17, but the macro may be undefined, and in #if statement the undefined macro will be expanded as 0 value.

But it's very unreliable.

They are defined as something like 201606, which I believe is a version of C++, not of the compiler...

Be careful. Section 15.11 [2] does not state that exactly. However, I hope toolchain implementation will define exactly what you said. Unfortunately, the (working draft of) standard does not force that.


Dear @J. Calleja

So, you can check if the feature exists by checking if the macro is defined.

Yes, but if you use C++2020, not C++98/03/11/14/17.

Or you can check for the feature version based on the macro value.

I'd like to add an extra comment. Please be aware of the following statement from [2], Section 15.11, p.455:

"Future versions of this International Standard might replace the values of these macros with greater values."

And I don't see anything which mentions this inside cppreference feature_test.

If you want to produce compatible code use constructions like:

#if __cpp_char8_t >= 201811L
///
#endif
Eulau answered 14/6, 2023 at 22:40 Comment(8)
You cannot use this mechanism in C++98/03/11/14/17 - This is not true for libstdc++. If your standard library version is recent enough, it will define those macros. They are not gated on the C++ standard version being set to 20 or greater during the build.Epistasis
@ComicSansMS. Ok, I will fix the text to "it's not reliable". Thank you very much.Eulau
open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4659.pdf - __cpp mentioned 0 times (A); In cpp reference (en.cppreference.com/w/cpp/feature_test) there is a mention that it is supported from C++20. There are several options (I) Bug in Cpp reference and bug in the working draft; (II) Bug in GCC; (III) GCC can do whatever they want and define what they want, but this guarantee nothing. In fact, Implementation can define any symbols starting with two underscores "__(.)*" or "_[A-Z]" starting from old C89.Eulau
The question is tagged gcc. There is no bug in the C++ standard, nor is there in libstdc++. Everything works as expected, your interpretation of the implications of this feature being introduced only in C++20 for the libstdc++ implementation is incorrect.Epistasis
I see. Can you provide a reference from which I can learn that this is introduced earlier? Because by this link - en.cppreference.com/w/cpp/feature_test "Feature testing (since C++20)"Eulau
@Epistasis I have provided two documents that support that this library feature appeared only in c++20, can you provide some material from your side? I am glad to learn, but you do not provide any source of information.Eulau
I did provide material in my first comment. Your answer is still suggesting that the fact that the question used -std=c++17 is of significance here, which is misleading. The only thing the accepted answer does not mention that libstdc++ only started gradually introducing those macros starting with version 9.2, which addresses why the setup in the question has the macro as undefined. What you wrote, while technically correct, I feel is irrelevant in the context of this question which, at the core, is about the meaning of the number the macro would have had if it was defined.Epistasis
You have provided a link to GCC source code and it's great. But the C++ Language is not defined by GCC (C++ compiler and C++ std. libraries) defined by C++ Standards.Eulau

© 2022 - 2024 — McMap. All rights reserved.