{"id":6036,"date":"2020-11-27T07:09:22","date_gmt":"2020-11-27T07:09:22","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/feature-testing-with-c-20\/"},"modified":"2023-10-20T10:52:32","modified_gmt":"2023-10-20T10:52:32","slug":"feature-testing-with-c-20","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/feature-testing-with-c-20\/","title":{"rendered":"Feature Testing with C++20"},"content":{"rendered":"<p>When your program&#8217;s compilation broke with a brand-new C++20 feature, you often end with a few questions: Did I do something wrong? Did I find a compiler bug? Does my compiler not yet support this feature? Thanks to the feature testing in C++20, the last question is easy to answer.<\/p>\n<p><!--more--><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5945\" style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/07\/TimelineCpp20CoreLanguage.png\" alt=\"TimelineCpp20CoreLanguage\" width=\"650\" height=\"262\" \/><\/p>\n<p>When I experiment with brand-new C++ features, I check which compiler implements the feature I&#8217;m interested in. This is when I visit<a href=\"https:\/\/en.cppreference.com\/w\/cpp\/compiler_support\"> cppreference.com<\/a>, search for the feature I want to try out, and hope that at least one compiler of the big three (GCC, Clang, MSCV) implements the new feature.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6031\" style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/11\/cpp20Support.png\" alt=\"cpp20Support\" width=\"600\" height=\"395\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/11\/cpp20Support.png 1120w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/11\/cpp20Support-300x197.png 300w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><\/p>\n<p>When I get the answer partially, it is not satisfying. Ultimately, I don&#8217;t know who was guilty when the compilation of the brand-new feature failed. There is a more thoughtful way in C++20 to detect if your compiler supports a requested feature.<\/p>\n<h2>Feature Testing<\/h2>\n<p>The header<span style=\"font-family: courier new, courier;\"> &lt;version&gt;<\/span> allows you to ask your compiler for its C++11 or later support. You can ask for attributes, features of the core language, or the library. <span style=\"font-family: courier new, courier;\">&lt;version&gt;<\/span> has about 200 macros defined, which expand to a number when the feature is implemented. The number stands for the year and month the feature was added to the C++ standard. These are the numbers for<span style=\"font-family: courier new, courier;\"> static_assert,<\/span> lambdas, and concepts.<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\">__cpp_static_assert  <span style=\"color: #ff6600;\">200410L<\/span>\n__cpp_lambdas  <span style=\"color: #ff6600;\">200907L<\/span>\n__cpp_concepts <span style=\"color: #ff6600;\">201907L<\/span>\n<\/pre>\n<\/div>\n<p>The cppreference.com page to<a href=\"https:\/\/en.cppreference.com\/w\/cpp\/feature_test\"> feature testing<\/a> put all macros together in a long, long source file.<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #0099ff; font-style: italic;\">\/\/ featureTest.cpp\n\/\/ from cppreference.com<\/span>\n\n<span style=\"color: #009999;\">#if __cplusplus &lt; 201100<\/span>\n<span style=\"color: #009999;\">#  error \"C++11 or better is required\"<\/span>\n<span style=\"color: #009999;\">#endif<\/span>\n \n<span style=\"color: #009999;\">#include &lt;algorithm&gt;<\/span>\n<span style=\"color: #009999;\">#include &lt;cstring&gt;<\/span>\n<span style=\"color: #009999;\">#include &lt;iomanip&gt;<\/span>\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\n<span style=\"color: #009999;\">#include &lt;string&gt;<\/span>\n \n<span style=\"color: #009999;\">#ifdef __has_include<\/span>\n<span style=\"color: #009999;\"># if __has_include(&lt;version&gt;)<\/span>\n<span style=\"color: #009999;\">#   include &lt;version&gt;<\/span>\n<span style=\"color: #009999;\"># endif<\/span>\n<span style=\"color: #009999;\">#endif<\/span>\n \n<span style=\"color: #009999;\">#define COMPILER_FEATURE_VALUE(value) #value<\/span>\n<span style=\"color: #009999;\">#define COMPILER_FEATURE_ENTRY(name) { #name, COMPILER_FEATURE_VALUE(name) },<\/span>\n \n<span style=\"color: #009999;\">#ifdef __has_cpp_attribute<\/span>\n<span style=\"color: #009999;\"># define COMPILER_ATTRIBUTE_VALUE_AS_STRING(s) #s<\/span>\n<span style=\"color: #009999;\"># define COMPILER_ATTRIBUTE_AS_NUMBER(x) COMPILER_ATTRIBUTE_VALUE_AS_STRING(x)<\/span>\n<span style=\"color: #009999;\"># define COMPILER_ATTRIBUTE_ENTRY(attr) \\<\/span>\n<span style=\"color: #009999;\">  { #attr, COMPILER_ATTRIBUTE_AS_NUMBER(__has_cpp_attribute(attr)) },<\/span>\n<span style=\"color: #009999;\">#else<\/span>\n<span style=\"color: #009999;\"># define COMPILER_ATTRIBUTE_ENTRY(attr) { #attr, \"_\" },<\/span>\n<span style=\"color: #009999;\">#endif<\/span>\n \n<span style=\"color: #0099ff; font-style: italic;\">\/\/ Change these options to print out only necessary info.<\/span>\n<span style=\"color: #006699; font-weight: bold;\">static<\/span> <span style=\"color: #006699; font-weight: bold;\">struct<\/span> PrintOptions {\n    constexpr <span style=\"color: #006699; font-weight: bold;\">static<\/span> <span style=\"color: #007788; font-weight: bold;\">bool<\/span> titles               <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">1<\/span>;\n    constexpr <span style=\"color: #006699; font-weight: bold;\">static<\/span> <span style=\"color: #007788; font-weight: bold;\">bool<\/span> attributes           <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">1<\/span>;\n    constexpr <span style=\"color: #006699; font-weight: bold;\">static<\/span> <span style=\"color: #007788; font-weight: bold;\">bool<\/span> general_features     <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">1<\/span>;\n    constexpr <span style=\"color: #006699; font-weight: bold;\">static<\/span> <span style=\"color: #007788; font-weight: bold;\">bool<\/span> core_features        <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">1<\/span>;\n    constexpr <span style=\"color: #006699; font-weight: bold;\">static<\/span> <span style=\"color: #007788; font-weight: bold;\">bool<\/span> lib_features         <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">1<\/span>;\n    constexpr <span style=\"color: #006699; font-weight: bold;\">static<\/span> <span style=\"color: #007788; font-weight: bold;\">bool<\/span> supported_features   <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">1<\/span>;\n    constexpr <span style=\"color: #006699; font-weight: bold;\">static<\/span> <span style=\"color: #007788; font-weight: bold;\">bool<\/span> unsupported_features <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">1<\/span>;\n    constexpr <span style=\"color: #006699; font-weight: bold;\">static<\/span> <span style=\"color: #007788; font-weight: bold;\">bool<\/span> sorted_by_value      <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">0<\/span>;\n    constexpr <span style=\"color: #006699; font-weight: bold;\">static<\/span> <span style=\"color: #007788; font-weight: bold;\">bool<\/span> cxx11                <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">1<\/span>;\n    constexpr <span style=\"color: #006699; font-weight: bold;\">static<\/span> <span style=\"color: #007788; font-weight: bold;\">bool<\/span> cxx14                <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">1<\/span>;\n    constexpr <span style=\"color: #006699; font-weight: bold;\">static<\/span> <span style=\"color: #007788; font-weight: bold;\">bool<\/span> cxx17                <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">1<\/span>;\n    constexpr <span style=\"color: #006699; font-weight: bold;\">static<\/span> <span style=\"color: #007788; font-weight: bold;\">bool<\/span> cxx20                <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">1<\/span>;\n    constexpr <span style=\"color: #006699; font-weight: bold;\">static<\/span> <span style=\"color: #007788; font-weight: bold;\">bool<\/span> cxx23                <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">0<\/span>;\n}   print;\n \n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> CompilerFeature {\n    CompilerFeature(<span style=\"color: #006699; font-weight: bold;\">const<\/span> <span style=\"color: #007788; font-weight: bold;\">char<\/span><span style=\"color: #555555;\">*<\/span> name <span style=\"color: #555555;\">=<\/span> nullptr, <span style=\"color: #006699; font-weight: bold;\">const<\/span> <span style=\"color: #007788; font-weight: bold;\">char<\/span><span style=\"color: #555555;\">*<\/span> value <span style=\"color: #555555;\">=<\/span> nullptr)\n        <span style=\"color: #555555;\">:<\/span> name(name), value(value) {}\n    <span style=\"color: #006699; font-weight: bold;\">const<\/span> <span style=\"color: #007788; font-weight: bold;\">char<\/span><span style=\"color: #555555;\">*<\/span> name; <span style=\"color: #006699; font-weight: bold;\">const<\/span> <span style=\"color: #007788; font-weight: bold;\">char<\/span><span style=\"color: #555555;\">*<\/span> value;\n};\n \n<span style=\"color: #006699; font-weight: bold;\">static<\/span> CompilerFeature cxx[] <span style=\"color: #555555;\">=<\/span> {\nCOMPILER_FEATURE_ENTRY(__cplusplus)\nCOMPILER_FEATURE_ENTRY(__cpp_exceptions)\nCOMPILER_FEATURE_ENTRY(__cpp_rtti)\n<span style=\"color: #009999;\">#if 0<\/span>\n<span style=\"color: #0099ff; font-style: italic;\">COMPILER_FEATURE_ENTRY(__GNUC__)<\/span>\n<span style=\"color: #0099ff; font-style: italic;\">COMPILER_FEATURE_ENTRY(__GNUC_MINOR__)<\/span>\n<span style=\"color: #0099ff; font-style: italic;\">COMPILER_FEATURE_ENTRY(__GNUC_PATCHLEVEL__)<\/span>\n<span style=\"color: #0099ff; font-style: italic;\">COMPILER_FEATURE_ENTRY(__GNUG__)<\/span>\n<span style=\"color: #0099ff; font-style: italic;\">COMPILER_FEATURE_ENTRY(__clang__)<\/span>\n<span style=\"color: #0099ff; font-style: italic;\">COMPILER_FEATURE_ENTRY(__clang_major__)<\/span>\n<span style=\"color: #0099ff; font-style: italic;\">COMPILER_FEATURE_ENTRY(__clang_minor__)<\/span>\n<span style=\"color: #0099ff; font-style: italic;\">COMPILER_FEATURE_ENTRY(__clang_patchlevel__)<\/span>\n<span style=\"color: #009999;\">#endif<\/span>\n};\n<span style=\"color: #006699; font-weight: bold;\">static<\/span> CompilerFeature cxx11[] <span style=\"color: #555555;\">=<\/span> {\nCOMPILER_FEATURE_ENTRY(__cpp_alias_templates)\nCOMPILER_FEATURE_ENTRY(__cpp_attributes)\nCOMPILER_FEATURE_ENTRY(__cpp_constexpr)\nCOMPILER_FEATURE_ENTRY(__cpp_decltype)\nCOMPILER_FEATURE_ENTRY(__cpp_delegating_constructors)\nCOMPILER_FEATURE_ENTRY(__cpp_inheriting_constructors)\nCOMPILER_FEATURE_ENTRY(__cpp_initializer_lists)\nCOMPILER_FEATURE_ENTRY(__cpp_lambdas)\nCOMPILER_FEATURE_ENTRY(__cpp_nsdmi)\nCOMPILER_FEATURE_ENTRY(__cpp_range_based_for)\nCOMPILER_FEATURE_ENTRY(__cpp_raw_strings)\nCOMPILER_FEATURE_ENTRY(__cpp_ref_qualifiers)\nCOMPILER_FEATURE_ENTRY(__cpp_rvalue_references)\nCOMPILER_FEATURE_ENTRY(__cpp_static_assert)\nCOMPILER_FEATURE_ENTRY(__cpp_threadsafe_static_init)\nCOMPILER_FEATURE_ENTRY(__cpp_unicode_characters)\nCOMPILER_FEATURE_ENTRY(__cpp_unicode_literals)\nCOMPILER_FEATURE_ENTRY(__cpp_user_defined_literals)\nCOMPILER_FEATURE_ENTRY(__cpp_variadic_templates)\n};\n<span style=\"color: #006699; font-weight: bold;\">static<\/span> CompilerFeature cxx14[] <span style=\"color: #555555;\">=<\/span> {\nCOMPILER_FEATURE_ENTRY(__cpp_aggregate_nsdmi)\nCOMPILER_FEATURE_ENTRY(__cpp_binary_literals)\nCOMPILER_FEATURE_ENTRY(__cpp_constexpr)\nCOMPILER_FEATURE_ENTRY(__cpp_decltype_auto)\nCOMPILER_FEATURE_ENTRY(__cpp_generic_lambdas)\nCOMPILER_FEATURE_ENTRY(__cpp_init_captures)\nCOMPILER_FEATURE_ENTRY(__cpp_return_type_deduction)\nCOMPILER_FEATURE_ENTRY(__cpp_sized_deallocation)\nCOMPILER_FEATURE_ENTRY(__cpp_variable_templates)\n};\n<span style=\"color: #006699; font-weight: bold;\">static<\/span> CompilerFeature cxx14lib[] <span style=\"color: #555555;\">=<\/span> {\nCOMPILER_FEATURE_ENTRY(__cpp_lib_chrono_udls)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_complex_udls)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_exchange_function)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_generic_associative_lookup)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_integer_sequence)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_integral_constant_callable)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_is_final)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_is_null_pointer)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_make_reverse_iterator)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_make_unique)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_null_iterators)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_quoted_string_io)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_result_of_sfinae)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_robust_nonmodifying_seq_ops)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_shared_timed_mutex)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_string_udls)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_transformation_trait_aliases)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_transparent_operators)\nCOMPILER_FEATURE_ENTRY(<span style=\"color: #007788; font-weight: bold;\">__cpp_lib_tuple_element_t<\/span>)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_tuples_by_type)\n};\n \n<span style=\"color: #006699; font-weight: bold;\">static<\/span> CompilerFeature cxx17[] <span style=\"color: #555555;\">=<\/span> {\nCOMPILER_FEATURE_ENTRY(__cpp_aggregate_bases)\nCOMPILER_FEATURE_ENTRY(__cpp_aligned_new)\nCOMPILER_FEATURE_ENTRY(__cpp_capture_star_this)\nCOMPILER_FEATURE_ENTRY(__cpp_constexpr)\nCOMPILER_FEATURE_ENTRY(__cpp_deduction_guides)\nCOMPILER_FEATURE_ENTRY(__cpp_enumerator_attributes)\nCOMPILER_FEATURE_ENTRY(__cpp_fold_expressions)\nCOMPILER_FEATURE_ENTRY(__cpp_guaranteed_copy_elision)\nCOMPILER_FEATURE_ENTRY(__cpp_hex_float)\nCOMPILER_FEATURE_ENTRY(__cpp_if_constexpr)\nCOMPILER_FEATURE_ENTRY(__cpp_inheriting_constructors)\nCOMPILER_FEATURE_ENTRY(__cpp_inline_variables)\nCOMPILER_FEATURE_ENTRY(__cpp_namespace_attributes)\nCOMPILER_FEATURE_ENTRY(__cpp_noexcept_function_type)\nCOMPILER_FEATURE_ENTRY(__cpp_nontype_template_args)\nCOMPILER_FEATURE_ENTRY(__cpp_nontype_template_parameter_auto)\nCOMPILER_FEATURE_ENTRY(__cpp_range_based_for)\nCOMPILER_FEATURE_ENTRY(__cpp_static_assert)\nCOMPILER_FEATURE_ENTRY(__cpp_structured_bindings)\nCOMPILER_FEATURE_ENTRY(__cpp_template_template_args)\nCOMPILER_FEATURE_ENTRY(__cpp_variadic_using)\n};\n<span style=\"color: #006699; font-weight: bold;\">static<\/span> CompilerFeature cxx17lib[] <span style=\"color: #555555;\">=<\/span> {\nCOMPILER_FEATURE_ENTRY(__cpp_lib_addressof_constexpr)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_allocator_traits_is_always_equal)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_any)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_apply)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_array_constexpr)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_as_const)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_atomic_is_always_lock_free)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_bool_constant)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_boyer_moore_searcher)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_byte)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_chrono)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_clamp)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_enable_shared_from_this)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_execution)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_filesystem)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_gcd_lcm)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_hardware_interference_size)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_has_unique_object_representations)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_hypot)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_incomplete_container_elements)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_invoke)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_is_aggregate)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_is_invocable)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_is_swappable)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_launder)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_logical_traits)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_make_from_tuple)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_map_try_emplace)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_math_special_functions)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_memory_resource)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_node_extract)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_nonmember_container_access)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_not_fn)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_optional)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_parallel_algorithm)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_raw_memory_algorithms)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_sample)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_scoped_lock)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_shared_mutex)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_shared_ptr_arrays)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_shared_ptr_weak_type)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_string_view)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_to_chars)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_transparent_operators)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_type_trait_variable_templates)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_uncaught_exceptions)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_unordered_map_try_emplace)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_variant)\nCOMPILER_FEATURE_ENTRY(<span style=\"color: #007788; font-weight: bold;\">__cpp_lib_void_t<\/span>)\n};\n \n<span style=\"color: #006699; font-weight: bold;\">static<\/span> CompilerFeature cxx20[] <span style=\"color: #555555;\">=<\/span> {\nCOMPILER_FEATURE_ENTRY(__cpp_aggregate_paren_init)\nCOMPILER_FEATURE_ENTRY(<span style=\"color: #007788; font-weight: bold;\">__cpp_char8_t<\/span>)\nCOMPILER_FEATURE_ENTRY(__cpp_concepts)\nCOMPILER_FEATURE_ENTRY(__cpp_conditional_explicit)\nCOMPILER_FEATURE_ENTRY(__cpp_consteval)\nCOMPILER_FEATURE_ENTRY(__cpp_constexpr)\nCOMPILER_FEATURE_ENTRY(__cpp_constexpr_dynamic_alloc)\nCOMPILER_FEATURE_ENTRY(__cpp_constexpr_in_decltype)\nCOMPILER_FEATURE_ENTRY(__cpp_constinit)\nCOMPILER_FEATURE_ENTRY(__cpp_deduction_guides)\nCOMPILER_FEATURE_ENTRY(__cpp_designated_initializers)\nCOMPILER_FEATURE_ENTRY(__cpp_generic_lambdas)\nCOMPILER_FEATURE_ENTRY(__cpp_impl_coroutine)\nCOMPILER_FEATURE_ENTRY(__cpp_impl_destroying_delete)\nCOMPILER_FEATURE_ENTRY(__cpp_impl_three_way_comparison)\nCOMPILER_FEATURE_ENTRY(__cpp_init_captures)\nCOMPILER_FEATURE_ENTRY(__cpp_modules)\nCOMPILER_FEATURE_ENTRY(__cpp_nontype_template_args)\nCOMPILER_FEATURE_ENTRY(__cpp_using_enum)\n};\n<span style=\"color: #006699; font-weight: bold;\">static<\/span> CompilerFeature cxx20lib[] <span style=\"color: #555555;\">=<\/span> {\nCOMPILER_FEATURE_ENTRY(__cpp_lib_array_constexpr)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_assume_aligned)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_atomic_flag_test)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_atomic_float)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_atomic_lock_free_type_aliases)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_atomic_ref)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_atomic_shared_ptr)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_atomic_value_initialization)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_atomic_wait)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_barrier)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_bind_front)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_bit_cast)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_bitops)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_bounded_array_traits)\nCOMPILER_FEATURE_ENTRY(<span style=\"color: #007788; font-weight: bold;\">__cpp_lib_char8_t<\/span>)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_chrono)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_concepts)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_constexpr_algorithms)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_constexpr_complex)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_constexpr_dynamic_alloc)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_constexpr_functional)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_constexpr_iterator)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_constexpr_memory)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_constexpr_numeric)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_constexpr_string)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_constexpr_string_view)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_constexpr_tuple)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_constexpr_utility)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_constexpr_vector)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_coroutine)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_destroying_delete)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_endian)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_erase_if)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_execution)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_format)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_generic_unordered_lookup)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_int_pow2)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_integer_comparison_functions)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_interpolate)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_is_constant_evaluated)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_is_layout_compatible)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_is_nothrow_convertible)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_is_pointer_interconvertible)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_jthread)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_latch)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_list_remove_return_type)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_math_constants)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_polymorphic_allocator)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_ranges)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_remove_cvref)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_semaphore)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_shared_ptr_arrays)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_shift)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_smart_ptr_for_overwrite)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_source_location)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_span)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_ssize)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_starts_ends_with)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_string_view)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_syncbuf)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_three_way_comparison)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_to_address)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_to_array)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_type_identity)\nCOMPILER_FEATURE_ENTRY(__cpp_lib_unwrap_ref)\n};\n \n<span style=\"color: #006699; font-weight: bold;\">static<\/span> CompilerFeature cxx23[] <span style=\"color: #555555;\">=<\/span> {\nCOMPILER_FEATURE_ENTRY(__cpp_cxx23_stub) <span style=\"color: #0099ff; font-style: italic;\">\/\/&lt; Populate eventually<\/span>\n};\n<span style=\"color: #006699; font-weight: bold;\">static<\/span> CompilerFeature cxx23lib[] <span style=\"color: #555555;\">=<\/span> {\nCOMPILER_FEATURE_ENTRY(__cpp_lib_cxx23_stub) <span style=\"color: #0099ff; font-style: italic;\">\/\/&lt; Populate eventually<\/span>\n};\n \n<span style=\"color: #006699; font-weight: bold;\">static<\/span> CompilerFeature attributes[] <span style=\"color: #555555;\">=<\/span> {\nCOMPILER_ATTRIBUTE_ENTRY(carries_dependency)\nCOMPILER_ATTRIBUTE_ENTRY(deprecated)\nCOMPILER_ATTRIBUTE_ENTRY(fallthrough)\nCOMPILER_ATTRIBUTE_ENTRY(likely)\nCOMPILER_ATTRIBUTE_ENTRY(maybe_unused)\nCOMPILER_ATTRIBUTE_ENTRY(nodiscard)\nCOMPILER_ATTRIBUTE_ENTRY(noreturn)\nCOMPILER_ATTRIBUTE_ENTRY(no_unique_address)\nCOMPILER_ATTRIBUTE_ENTRY(unlikely)\n};\n \nconstexpr <span style=\"color: #007788; font-weight: bold;\">bool<\/span> <span style=\"color: #cc00ff;\">is_feature_supported<\/span>(<span style=\"color: #006699; font-weight: bold;\">const<\/span> CompilerFeature<span style=\"color: #555555;\">&amp;<\/span> x) {\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> x.value[<span style=\"color: #ff6600;\">0<\/span>] <span style=\"color: #555555;\">!=<\/span> <span style=\"color: #cc3300;\">'_'<\/span> <span style=\"color: #555555;\">&amp;&amp;<\/span> x.value[<span style=\"color: #ff6600;\">0<\/span>] <span style=\"color: #555555;\">!=<\/span> <span style=\"color: #cc3300;\">'0'<\/span> ;\n}\n \n<span style=\"color: #006699; font-weight: bold;\">inline<\/span> <span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">print_compiler_feature<\/span>(<span style=\"color: #006699; font-weight: bold;\">const<\/span> CompilerFeature<span style=\"color: #555555;\">&amp;<\/span> x) {\n    constexpr <span style=\"color: #006699; font-weight: bold;\">static<\/span> <span style=\"color: #007788; font-weight: bold;\">int<\/span> max_name_length <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">44<\/span>; <span style=\"color: #0099ff; font-style: italic;\">\/\/&lt; Update if necessary<\/span>\n    std<span style=\"color: #555555;\">::<\/span>string value{ is_feature_supported(x) <span style=\"color: #555555;\">?<\/span> x.value <span style=\"color: #555555;\">:<\/span> <span style=\"color: #cc3300;\">\"------\"<\/span> };\n    <span style=\"color: #006699; font-weight: bold;\">if<\/span> (value.back() <span style=\"color: #555555;\">==<\/span> <span style=\"color: #cc3300;\">'L'<\/span>) value.pop_back(); <span style=\"color: #0099ff; font-style: italic;\">\/\/~ 201603L -&gt; 201603<\/span>\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ value.insert(4, 1, '-'); \/\/~ 201603 -&gt; 2016-03<\/span>\n    <span style=\"color: #006699; font-weight: bold;\">if<\/span> ( (print.supported_features <span style=\"color: #555555;\">&amp;&amp;<\/span> is_feature_supported(x))\n        <span style=\"color: #555555;\">||<\/span> (print.unsupported_features <span style=\"color: #555555;\">&amp;&amp;<\/span> <span style=\"color: #555555;\">!<\/span>is_feature_supported(x))) {\n            std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>left <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>setw(max_name_length)\n                      <span style=\"color: #555555;\">&lt;&lt;<\/span> x.name <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\" \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> value <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n    }\n}\n \n<span style=\"color: #006699; font-weight: bold;\">template<\/span><span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">size_t<\/span> N<span style=\"color: #555555;\">&gt;<\/span>\n<span style=\"color: #006699; font-weight: bold;\">inline<\/span> <span style=\"color: #007788; font-weight: bold;\">void<\/span> show(<span style=\"color: #007788; font-weight: bold;\">char<\/span> <span style=\"color: #006699; font-weight: bold;\">const<\/span><span style=\"color: #555555;\">*<\/span> title, CompilerFeature (<span style=\"color: #555555;\">&amp;<\/span>features)[N]) {\n    <span style=\"color: #006699; font-weight: bold;\">if<\/span> (print.titles) {\n        std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>left <span style=\"color: #555555;\">&lt;&lt;<\/span> title <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n    }\n    <span style=\"color: #006699; font-weight: bold;\">if<\/span> (print.sorted_by_value) {\n        std<span style=\"color: #555555;\">::<\/span>sort(std<span style=\"color: #555555;\">::<\/span>begin(features), std<span style=\"color: #555555;\">::<\/span>end(features),\n            [](CompilerFeature <span style=\"color: #006699; font-weight: bold;\">const<\/span><span style=\"color: #555555;\">&amp;<\/span> lhs, CompilerFeature <span style=\"color: #006699; font-weight: bold;\">const<\/span><span style=\"color: #555555;\">&amp;<\/span> rhs) {\n                <span style=\"color: #006699; font-weight: bold;\">return<\/span> std<span style=\"color: #555555;\">::<\/span>strcmp(lhs.value, rhs.value) <span style=\"color: #555555;\">&lt;<\/span> <span style=\"color: #ff6600;\">0<\/span>;\n            });\n    }\n    <span style=\"color: #006699; font-weight: bold;\">for<\/span> (<span style=\"color: #006699; font-weight: bold;\">const<\/span> CompilerFeature<span style=\"color: #555555;\">&amp;<\/span> x <span style=\"color: #555555;\">:<\/span> features) {\n        print_compiler_feature(x);\n    }\n}\n \n<span style=\"color: #007788; font-weight: bold;\">int<\/span> main() {\n    <span style=\"color: #006699; font-weight: bold;\">if<\/span> (print.general_features) show(<span style=\"color: #cc3300;\">\"C++ GENERAL\"<\/span>, cxx);\n    <span style=\"color: #006699; font-weight: bold;\">if<\/span> (print.cxx11 <span style=\"color: #555555;\">&amp;&amp;<\/span> print.core_features) show(<span style=\"color: #cc3300;\">\"C++11 CORE\"<\/span>, cxx11);\n    <span style=\"color: #006699; font-weight: bold;\">if<\/span> (print.cxx14 <span style=\"color: #555555;\">&amp;&amp;<\/span> print.core_features) show(<span style=\"color: #cc3300;\">\"C++14 CORE\"<\/span>, cxx14);\n    <span style=\"color: #006699; font-weight: bold;\">if<\/span> (print.cxx14 <span style=\"color: #555555;\">&amp;&amp;<\/span> print.lib_features ) show(<span style=\"color: #cc3300;\">\"C++14 LIB\"<\/span> , cxx14lib);\n    <span style=\"color: #006699; font-weight: bold;\">if<\/span> (print.cxx17 <span style=\"color: #555555;\">&amp;&amp;<\/span> print.core_features) show(<span style=\"color: #cc3300;\">\"C++17 CORE\"<\/span>, cxx17);\n    <span style=\"color: #006699; font-weight: bold;\">if<\/span> (print.cxx17 <span style=\"color: #555555;\">&amp;&amp;<\/span> print.lib_features ) show(<span style=\"color: #cc3300;\">\"C++17 LIB\"<\/span> , cxx17lib);\n    <span style=\"color: #006699; font-weight: bold;\">if<\/span> (print.cxx20 <span style=\"color: #555555;\">&amp;&amp;<\/span> print.core_features) show(<span style=\"color: #cc3300;\">\"C++20 CORE\"<\/span>, cxx20);\n    <span style=\"color: #006699; font-weight: bold;\">if<\/span> (print.cxx20 <span style=\"color: #555555;\">&amp;&amp;<\/span> print.lib_features ) show(<span style=\"color: #cc3300;\">\"C++20 LIB\"<\/span> , cxx20lib);\n    <span style=\"color: #006699; font-weight: bold;\">if<\/span> (print.cxx23 <span style=\"color: #555555;\">&amp;&amp;<\/span> print.core_features) show(<span style=\"color: #cc3300;\">\"C++23 CORE\"<\/span>, cxx23);\n    <span style=\"color: #006699; font-weight: bold;\">if<\/span> (print.cxx23 <span style=\"color: #555555;\">&amp;&amp;<\/span> print.lib_features ) show(<span style=\"color: #cc3300;\">\"C++23 LIB\"<\/span> , cxx23lib);\n    <span style=\"color: #006699; font-weight: bold;\">if<\/span> (print.attributes) show(<span style=\"color: #cc3300;\">\"ATTRIBUTES\"<\/span>, attributes);\n}\n<\/pre>\n<\/div>\n<p>Of course, the length of the source file is overwhelming. When you want to know more about each macro, visit the page to <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/feature_test\">feature testing<\/a>. In particular, they provide each macro with a link that can use to get more information about a feature. For example, here is the table on attributes:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6032\" style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/11\/attributes.png\" alt=\"attributes\" width=\"400\" height=\"211\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/11\/attributes.png 699w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/11\/attributes-300x158.png 300w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><\/p>\n<p>To finish my presentation of the <code>&lt;version&gt;<\/code> header and its macros, I execute the program on the brand-new GCC, Clang, and MSVC compiler. I used <a href=\"https:\/\/godbolt.org\/\">Compiler Explorer<\/a> for the GCC and Clang compilers. On Windows, I had to enable preprocessor macros with the flag<code> \/Zc:__cplusplus<\/code>. Additionally, I compiled on all three platforms with C++20 support.<\/p>\n<p>For obvious reasons, I only display the support of the C++20 core language.<\/p>\n<ul>\n<li><strong>GCC 10.2<\/strong><\/li>\n<\/ul>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6033\" style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/11\/gccCoreCpp20.png\" alt=\"gccCoreCpp20\" width=\"400\" height=\"367\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/11\/gccCoreCpp20.png 557w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/11\/gccCoreCpp20-300x275.png 300w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><\/p>\n<ul>\n<li><strong>Clang 11.0<\/strong><\/li>\n<\/ul>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6034\" style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/11\/clangCoreCpp20.png\" alt=\"clangCoreCpp20\" width=\"400\" height=\"380\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/11\/clangCoreCpp20.png 538w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/11\/clangCoreCpp20-300x285.png 300w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><\/p>\n<ul>\n<li><strong>MSVC 19.27<\/strong><\/li>\n<\/ul>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6035\" style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/11\/msvc2CoreCpp20.png\" alt=\"msvc2CoreCpp20\" width=\"500\" height=\"385\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/11\/msvc2CoreCpp20.png 490w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/11\/msvc2CoreCpp20-300x231.png 300w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\" \/><\/p>\n<p>The three screenshots speak a clear message about the big three. Their C++20 core language support is quite good at this early stage.<\/p>\n<p>The<a href=\"https:\/\/en.cppreference.com\/w\/cpp\/header\/type_traits\"> type-traits library <\/a>gets quite an interesting function.<\/p>\n<h2><code>std::is_constant_evaluated<\/code><\/h2>\n<p>The function <code>std::is_constant_evaluated<\/code> determines whether the function call occurs within a constant-evaluated context or not. Why do we need this function from the <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/header\/type_traits\">type-traits library<\/a>? In C++20, we have roughly spoken three kinds of functions:<\/p>\n<ul>\n<li><a href=\"https:\/\/www.modernescpp.com\/index.php\/c-20-consteval-and-constinit\"><code>consteval<\/code><\/a> declared functions execute at compile-time:<code> consteval int alwaysCompiletime<\/code><\/li>\n<li><code>constexpr<\/code> declared functions can be executed at compile-time or runtime: <code>constexpr int itDepends<\/code><\/li>\n<li>Usual functions execute at runtime:<code> int alwaysRuntime<\/code><\/li>\n<\/ul>\n<p>Now, I have to write about the complicated case: <code>constexpr<\/code>. A <code>constexpr<\/code> function call occurs within a constant-evaluated context or not. Sometimes these functions should behave differently whether the function call occurs within a constant-evaluated context or not. A <code>constexpr<\/code> function such as<code> getSum<\/code> has the potential to run at compile-time.<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\">constexpr <span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">getSum<\/span>(<span style=\"color: #007788; font-weight: bold;\">int<\/span> l, <span style=\"color: #007788; font-weight: bold;\">int<\/span> r) {\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> l <span style=\"color: #555555;\">+<\/span> r;\n}\n<\/pre>\n<\/div>\n<p>How can be sure that the function call occurs within a constant-evaluated context or not?<\/p>\n<ul>\n<li>A constant-evaluated context\n<ul>\n<li>implicit: Call in a constant expression<\/li>\n<li>explicit: Request the result using constexpr<\/li>\n<\/ul>\n<\/li>\n<li>A non-constant-evaluated context\n<ul>\n<li>Function arguments are not constant expressions<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<ul>\n<li style=\"list-style-type: none;\"><\/li>\n<\/ul>\n<p><a href=\"https:\/\/en.cppreference.com\/w\/cpp\/types\/is_constant_evaluated\">cppreference.com<\/a> shows a smart use case.\u00a0At compile-time, you calculate the power of two numbers manually; at runtime, you use <code>std::pow<\/code>.<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #0099ff; font-style: italic;\">\/\/ constantEvaluated.cpp<\/span>\n\n<span style=\"color: #009999;\">#include &lt;type_traits&gt;<\/span>\n<span style=\"color: #009999;\">#include &lt;cmath&gt;<\/span>\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\n \nconstexpr <span style=\"color: #007788; font-weight: bold;\">double<\/span> <span style=\"color: #cc00ff;\">power<\/span>(<span style=\"color: #007788; font-weight: bold;\">double<\/span> b, <span style=\"color: #007788; font-weight: bold;\">int<\/span> x) {\n    <span style=\"color: #006699; font-weight: bold;\">if<\/span> (std<span style=\"color: #555555;\">::<\/span>is_constant_evaluated() <span style=\"color: #555555;\">&amp;&amp;<\/span> <span style=\"color: #555555;\">!<\/span>(b <span style=\"color: #555555;\">==<\/span> <span style=\"color: #ff6600;\">0.0<\/span> <span style=\"color: #555555;\">&amp;&amp;<\/span> x <span style=\"color: #555555;\">&lt;<\/span> <span style=\"color: #ff6600;\">0<\/span>)) {\n        \n        <span style=\"color: #006699; font-weight: bold;\">if<\/span> (x <span style=\"color: #555555;\">==<\/span> <span style=\"color: #ff6600;\">0<\/span>)\n            <span style=\"color: #006699; font-weight: bold;\">return<\/span> <span style=\"color: #ff6600;\">1.0<\/span>;\n        <span style=\"color: #007788; font-weight: bold;\">double<\/span> r <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">1.0<\/span>, p <span style=\"color: #555555;\">=<\/span> x <span style=\"color: #555555;\">&gt;<\/span> <span style=\"color: #ff6600;\">0<\/span> <span style=\"color: #555555;\">?<\/span> b <span style=\"color: #555555;\">:<\/span> <span style=\"color: #ff6600;\">1.0<\/span> <span style=\"color: #555555;\">\/<\/span> b;\n        <span style=\"color: #006699; font-weight: bold;\">auto<\/span> u <span style=\"color: #555555;\">=<\/span> <span style=\"color: #007788; font-weight: bold;\">unsigned<\/span>(x <span style=\"color: #555555;\">&gt;<\/span> <span style=\"color: #ff6600;\">0<\/span> <span style=\"color: #555555;\">?<\/span> x <span style=\"color: #555555;\">:<\/span> <span style=\"color: #555555;\">-<\/span>x);\n        <span style=\"color: #006699; font-weight: bold;\">while<\/span> (u <span style=\"color: #555555;\">!=<\/span> <span style=\"color: #ff6600;\">0<\/span>) {\n            <span style=\"color: #006699; font-weight: bold;\">if<\/span> (u <span style=\"color: #555555;\">&amp;<\/span> <span style=\"color: #ff6600;\">1<\/span>) r <span style=\"color: #555555;\">*=<\/span> p;\n            u <span style=\"color: #555555;\">\/=<\/span> <span style=\"color: #ff6600;\">2<\/span>;\n            p <span style=\"color: #555555;\">*=<\/span> p;\n        }\n        <span style=\"color: #006699; font-weight: bold;\">return<\/span> r;\n    } \n    <span style=\"color: #006699; font-weight: bold;\">else<\/span> {\n        <span style=\"color: #006699; font-weight: bold;\">return<\/span> std<span style=\"color: #555555;\">::<\/span>pow(b, <span style=\"color: #007788; font-weight: bold;\">double<\/span>(x));\n    }\n}\n \n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>() {\n    \n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\n    \n    constexpr <span style=\"color: #007788; font-weight: bold;\">double<\/span> kilo1 <span style=\"color: #555555;\">=<\/span> power(<span style=\"color: #ff6600;\">10.0<\/span>, <span style=\"color: #ff6600;\">3<\/span>);\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"kilo1: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> kilo1 <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\n    \n    <span style=\"color: #007788; font-weight: bold;\">int<\/span> n <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">3<\/span>;\n    <span style=\"color: #007788; font-weight: bold;\">double<\/span> kilo2 <span style=\"color: #555555;\">=<\/span> power(<span style=\"color: #ff6600;\">10.0<\/span>, n);\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"kilo2: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> kilo2 <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\n    \n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\n    \n}\n<\/pre>\n<\/div>\n<p>There is one interesting observation I want to share. It is possible to use <code>std::is_constant_evaluated<\/code> in an as <code>consteval<\/code> declared function or in a function that can only run at runtime. Of course, the result of these calls is always <code>true<\/code> or <code>false<\/code>.<\/p>\n<h2>What&#8217;s next?<\/h2>\n<p>I&#8217;m nearly done with my presentation on the C++20 library. Only two features are still missing bevor I dive into concurrency in C++20: the bit manipulation library and <code>std::source_location<\/code>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>When your program&#8217;s compilation broke with a brand-new C++20 feature, you often end with a few questions: Did I do something wrong? Did I find a compiler bug? Does my compiler not yet support this feature? Thanks to the feature testing in C++20, the last question is easy to answer.<\/p>\n","protected":false},"author":21,"featured_media":5945,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[375],"tags":[],"class_list":["post-6036","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-c-20"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/6036","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/users\/21"}],"replies":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/comments?post=6036"}],"version-history":[{"count":2,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/6036\/revisions"}],"predecessor-version":[{"id":8521,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/6036\/revisions\/8521"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/5945"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=6036"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=6036"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=6036"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}