C++20 Features and Fixes in VS 2019 16.1 through 16.6

Stephan T. Lavavej - MSFT

What’s New

We’ve been busy implementing C++20 features in MSVC’s compiler and Standard Library, and migrating the latter to microsoft/STL on GitHub – in fact, we’ve been so busy that we haven’t posted a C++ toolset changelog since the VS 2019 16.0 toolset changelog. So, here are the compiler features and STL features/fixes that have shipped for production use in the last year.

As a reminder, the /std:c++17 and /std:c++latest compiler options are necessary to use C++17 and C++20 features.

 

VS 2019 16.1

New features (all thanks to our intern Paolo Torres):

 

New language features:

 

Correctness fixes:

  • Fixed a regression in VS 2019 16.0 where the bucket count for unordered associative containers might have become higher than intended when using the allocator-extended move constructor with unequal allocators.
  • Removed a not-present-in-standard polar function in <complex> that prevented compiling polar<float>(1.0, 2.0).
  • Implemented the resolution of LWG-3025, which fixes the deduction guides of map, multimap, unordered_map, and unordered_multimap to enable deduction from e.g. {pair{1, 2}, {3, 4}}.
  • Implemented the resolution of LWG-3012, which requires the argument to std::atomic to be copy constructible, move constructible, copy assignable, and move assignable in addition to the previous trivially copyable requirement.
  • Removed non-standard std::identity to clear the way for the new standard std::identity. (Thanks to our intern, Paolo Torres!)
  • Rewrote <atomic> to improve throughput and codegen – especially for debug compiles – and fixed a bug in constexpr construction of atomic<T*> under Clang.

 

Performance and throughput fixes:

  • Removed several internal “convenience” functions previously used to implement STL features that had poor debug codegen interaction with per-function-overhead options like /RTC1 and /JMC.
  • Changed complex to call std::hypot instead of a slightly different library implementation, to engage compiler optimizations for hypot by Vivian An in the optimizer under /fp:fast.
  • Fixed vector<bool>::reference’s swap function to be a hidden friend, improving compiler diagnostics when swapping an unrelated unswappable type.
  • Fixed several places where the associative containers were using iterator-debugging-enabled iterators internally.
  • Optimized the unordered associative container rehash operation by removing self-recursion and try regions.
  • Improved throughput of <type_traits> by defining class templates in terms of variable templates when possible and drastically simplifying make_signed_t and make_unsigned_t.

 

Other improvements:

  • The Standard requires implementations to support a certain set of facet specializations. MSVC’s STL permitted non-Standard facet specializations to be used, with often-undesirable consequences. In this release, we implemented an off-by-default mode to enforce that only Standard facet specializations are used, emitting a static_assert for non-Standard usage. Compiling with /D_ENFORCE_FACET_SPECIALIZATIONS=1 will request this mode.

 

VS 2019 16.2

New features:

 

New language features:

 

Correctness fixes:

  • Fixed basic_string to provide the strong exception safety guarantee on copy assignment with unequal propagate_on_container_copy_assignment allocators.
  • Fixed _ITERATOR_DEBUG_LEVEL == 1 to no longer do iterator ownership assertions for node-based containers forward_list, list, set, map, multiset, multimap, unordered_set, unordered_map, unordered_multiset, or unordered_multimap. Conditions were discovered where these assertions rejected valid programs in the presence of splices, merges, or usage of C++17 node_handle.
  • Fixed list’s remove_if algorithm to tolerate container self-references as an extension permitted but not required by the standard.
  • Fixed forward_list::erase_after’s handling of double-exclusive ranges to never cause the container to become corrupted. Edge cases in this handling were found by libcxx’s test suite.
  • Fixed multiset and multimap to use the supplied hint to control relative element insertion order in the range of equivalent elements.
  • Fixed <filesystem> to interpret the Win32 error code ERROR_INVALID_NAME as a “file not found” error rather than a fatal I/O error for the purposes of status().
  • Fixed istream::sentry to not set badbit upon encountering end-of-file when exceptions() has eofbit set.
  • Fixed istream::sync() to tolerate streambufs with throwing pubsync().
  • Defended against macroization of new C++20 keywords in <xkeycheck.h>.
  • Fixed a conflict between mbctype.h and <charconv>. mbctype.h macroizes _M2, so <charconv> now avoids using that as an identifier.
  • Fixed deque iterator orphaning, which was causing crashes in debug mode.
  • Fixed from_chars() bugs affecting certain corner cases with subnormals.
  • Changed from_chars() behavior for overflow/underflow to align with strtod() behavior. (Note that this is tracked by LWG-3081 with a different proposed resolution.)

 

Performance and throughput fixes:

  • Applied if-constexpr to even more places, including <memory>, <functional>, and the allocator-range algorithms used to implement deque, string, and vector.
  • Fixed tree-based associative containers set, map, multiset, and multimap to always use the hint parameter if supplied.
  • Fixed tree-based associative containers set, map, multiset, and multimap to have reduced code size because the same binary search operation now powers both insertion operations like insert or emplace, as well as plain lookup functions like lower_bound or find. Previously this was duplicated in a manner impossible for the optimizer to merge.
  • Removed more try regions from <memory>.
  • Optimized associative containers map, set, unordered_map, and unordered_set emplacement to avoid allocating nodes when inserting duplicate keys if the container is passed an instance of the key directly.
  • Fixed forward_list::resize to avoid a redundant traversal of the forward_list to calculate the size.
  • Reduced forward_list::insert_after’s iterator debugging costs.
  • In <charconv>, fixed shortest to_chars() is even faster, optimized by Ryu Printf.

 

Other improvements:

  • Increased the STL’s required version of Clang to 8.0.0.

 

VS 2019 16.3

New features:

 

New language features:

 

Correctness fixes:

  • Implemented the is_trivial/is_trivial_v type trait in terms of is_constructible and is_trivially_copyable to work around bugs in MSVC and Clang’s __is_trivial intrinsics.
  • Detected more non-compiler tools (Qt’s MOC and Windows’ midl, in addition to pre-existing detection for Windows’ resource compiler) that sometimes process C++ header files, and used the preprocessor to hide the contents of STL headers from them to avoid breakage when the STL uses newer language constructs that such tools don’t understand. (This is a best-effort attempt; ideally folks would not point such tools at STL headers in the first place.)
  • Implemented comparison operations for stack and queue in terms of the corresponding operations on the adapted container instead of implementing all in terms of == and < on the adapted container.
  • Fixed a bug in pmr::monotonic_resource::release that resulted in use of freed memory on subsequent allocations from the monotonic_resource.
  • The STL now uses allocator::construct for container user-supplied types only, so allocators that default-initialize rather than value-initialize no longer break the containers.
  • The STL now doesn’t create temporary values on the stack without going through allocator construct for containers.
  • Defended against more off-by-default warnings requested by customers, such as C4582, C4583, C4587, C4588, and C4800.
  • current_exception() and current_exceptions() now return correct values in terminate handlers.
  • Implemented LWG-2996 “Missing rvalue overloads for shared_ptr operations”.
  • Implemented LWG-3038 “polymorphic_allocator::allocate should not allow integer overflow to create vulnerabilities”.
  • Implemented LWG-3074 “Non-member functions for valarray should only deduce from the valarray”.
  • Implemented LWG-3130 “[input.output] needs many addressof”.
  • Implemented LWG-3131 “addressof all the things”.
  • Simplified is_void_v, is_integral_v, and is_floating_point_v. Previously, we were explicitly specializing non-inline variable templates in C++14 mode, which is technically forbidden by the Standard and was causing headaches for Clang.

 

Performance and throughput fixes:

  • Use the __is_same intrinsic to implement the is_same/is_same_v type trait on Clang.
  • Node-based containers will reuse nodes more often when performing bulk operations rather than deallocating and reallocating everything. For example, given a list L containing C elements, L.assign(N, T) now deallocates only the unused C – N elements or allocates only the newly needed N – C elements, rather than freeing all C elements followed by allocating all N elements.

 

Other improvements:

  • <filesystem> no longer includes <experimental/filesystem>.
  • <experimental/filesystem> now emits a warning/error: “The <experimental/filesystem> header providing std::experimental::filesystem is deprecated by Microsoft and will be REMOVED. It is superseded by the C++17 <filesystem> header providing std::filesystem. You can define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING to acknowledge that you have received this warning.”
  • Deleted the non-Standard <allocators>, <stdexcpt.h>, and <typeinfo.h> headers.
  • Removed unnecessary “inline” keywords in the STL.
  • Improved the STL’s /Wall cleanliness. Note that this is a work in progress tracked by microsoft/STL#186.
  • Eliminated all C casts in the STL’s headers.
  • Strengthened noexcept for various functions.

 

VS 2019 16.4

New features:

  • Increased the STL’s required version of Clang to 8.0.1. This notably enables STL char8_t support with Clang, whose previous versions didn’t know how to mangle char8_t in the MS ABI.
  • Implemented P1754R1 “Rename Concepts To standard_case”.
  • Implemented parts of P0896R4 “<ranges>”:
    • Changes to iterator_traits
    • Addition of the iterator and range concepts
    • ranges::iter_move and ranges::iter_swap customization points
    • Range access customization points (normal/const/reverse/const-reverse variations of ranges::begin and ranges::end, ranges::size, ranges::empty, ranges::data, and ranges::cdata)
    • The associated type aliases: ranges::iterator_t, ranges::sentinel_t, ranges::range_value_t, ranges::range_reference_t, ranges::range_difference_t, and ranges::range_rvalue_reference_t
    • Modifications necessary for array, basic_string, basic_string_view, valarray, and vector to model the contiguous_range concept
  • Activated STL [[nodiscard]] attributes in C++14 mode for MSVC.
  • Implemented general precision to_chars(), completing C++17 <charconv>.

 

New language features:

 

Correctness fixes:

  • Explicitly specified the underlying types of some enumeration types in <regex> that use bitwise operations to avoid storing an unrepresentable value (which is formally undefined behavior, as noted by Clang’s UBSAN).
  • Implemented LWG-3196 “std::optional<T> is ill-formed if T is an array” (it was already ill-formed, but now there is a friendly static_assert message). Slightly improved throughput by simplifying the metaprogramming for optional<T>’s comparisons with T and by using “if constexpr” instead of tag dispatch in optional::swap.
  • Applied a user-supplied work around for an IntelliSense bug in common_reference.
  • std::filesystem::directory_entry no longer claims nonexistent files are regular files.
  • std::filesystem::directory_iterator(“”) no longer iterates over current_path().
  • std::filesystem::recursive_directory_iterator no longer triggers infinite loops when passed paths containing embedded nulls.
  • Fixed an edge case in iterator debugging support during list::splice where the container size could be updated incorrectly.
  • Improved floating-point <charconv> handling of NaN.

 

Performance and throughput fixes:

  • Reduced the amount of contents included by <compare>.
  • Improved list and forward_list’s member algorithms to not need distance/advance calls which were inefficient given that they are non-random-access ranges.
  • Partially implemented LWG-2550 “unordered containers’ clear() should be O(number of elements)” as far as our current ABI allows – this speeds up unordered containers with a large number of buckets but few elements. We can only do this if the hash function is noexcept because erasing an element when not walking each bucket requires evaluating the hash function.
  • Strengthened noexcept on several container functions.
  • atomic<8 bytes> is now implemented with an ordinary load on x86 rather than cmpxchg8b.
  • Improved throughput by using conditional explicit in pair/tuple/optional for MSVC and the IntelliSense compiler.

 

Other improvements:

  • Removed the _HAS_SPECIAL_MATH “escape hatch” macro which suppressed definition of the C++17 mathematical special functions in <cmath> when defined to 0.

 

VS 2019 16.5

Please see https://github.com/microsoft/STL/wiki/Changelog for release notes for the STL in all future Visual Studio releases.

 

New language features:

 

VS 2019 16.6

Please see https://github.com/microsoft/STL/wiki/Changelog for release notes for the STL in all future Visual Studio releases.

 

New language features and national body comment resolutions:

 

More Information

For Visual Studio changes (beyond the C++ toolset) and download links, see the VS Release Notes and VS Preview Release Notes. You can report bugs through Developer Community, and you can also report STL bugs via microsoft/STL GitHub issues.

16 comments

Comments are closed. Login to edit/delete your existing comments

    • Stephan T. Lavavej - MSFT
      Stephan T. Lavavej - MSFTMicrosoft employee

      I’ve asked the compiler frontend team to comment about the current status of modules; on the library side we’ve been working towards completing the “standard library header units” feature; my coworker Steve fixed a conflicting definition of SIZE_MAX in the VCRuntime headers, and when that fix ships in a public Preview, we should be able to add test coverage verifying that all Standard Library headers are importable. We’ve also worked on internal test coverage (I reduced a few compiler bugs that our frontend dev Cameron fixed).

    • Avatar
      Gabriel Dos Reis

      The Visual C++ team has been making good progress on C++20 Modules. We will publish a blog post detailing newly implemented functionalities in the near future (no specific date yet), on the MSVC toolset, the IDE integration (IntelliSense), project and build integration, linker support for module strong ownership, and more.

  • Avatar
    jasper mitchel

    Great to hear all the progress! Lots of good changes. I knew there were fixes going into every release but it’d be nice to see this information in the release notes. Usually the VS notes are mostly full of non-C++ changes.

    Is there any update on when the experimental preprocessor, experimental lambda, or experimental include features will be out of ‘experimental’ status? I know I wanted to use the new preprocessor but was blocked by the WinSDK not being moved over yet.

    • Stephan T. Lavavej - MSFT
      Stephan T. Lavavej - MSFTMicrosoft employee

      I’ve asked compiler frontend devs to provide more detailed info; according to my limited understanding, the experimental preprocessor is becoming officially supported as /Zc:preprocessor due to Elnar’s great work in the frontend (and my coworker Charlie added test coverage for this to the STL). The new lambda processor is being gradually enabled as JonCaves has carefully ironed out the remaining compatibility issues (right now I believe it’s implied by /std:c++latest only, but my info could be incorrect/outdated). I believe that there have been no recent changes to the “external warnings” feature.
      We also encountered those WinSDK compatibility issues (for which we have workarounds in the STL’s test coverage); the last I heard, these have been reported to the WinSDK team, but there is no ETA for a fix yet.

  • Avatar
    문성 장

    Thank you for your nice works!

    Do you have any detailed plan to implement P1141R2 (Yet another approach for constrained declarations) ?
    http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1141r2.html

    The MSVC conformance table says “Partial” ( https://docs.microsoft.com/en-us/cpp/overview/visual-cpp-language-conformance?view=vs-2019 )
    but I could not find any noticeable implementation so far.
    vc: https://godbolt.org/z/Q9pU4c
    clang: https://godbolt.org/z/5fYVqx

    • Stephan T. Lavavej - MSFT
      Stephan T. Lavavej - MSFTMicrosoft employee

      I’ve asked the compiler frontend devs to comment about this too; I do know that the feature is marked as Partial because we’ve implemented P1141R2’s patches to the concepts wording, but not the actual feature that it adds. Perhaps this was confusing; if so, I am to blame 🙂 (This was back when I attempted to keep track of every Core Language feature’s status in addition to all STL features; I maintained an Excel spreadsheet that was then used as a basis for that Microsoft Docs table.)

    • Avatar
      xiangfanMicrosoft employee

      Hi,
      As STL explained, the partial state is for the wording in P1141R2 which is related to concept (it amends the syntax for the constrained non-type template argument).
      The 16.7 compiler implements the placeholder-type-specifier in P1141R2 and we plan to implement the abbreviated function template in 16.8.

  • Avatar
    Shuo Yu

    I know that this is unrelated but I don’t know the proper place to ask this question… May I ask when (or in which version) are you planning to implement full C++20 coroutine support (not the one with “/await”)? It seems that C++20 coroutine will be partially implemented in 16.8 but without the symmetric transfer part. Thanks!

    • Stephan T. Lavavej - MSFT
      Stephan T. Lavavej - MSFTMicrosoft employee

      Our compiler front-end dev Jonathan Emmett has contributed the Standard <coroutine> header, including noop_coroutine implemented by our compiler front-end intern Ayesha Gagguturi, for 16.8 (see https://github.com/microsoft/STL/blob/87dc1d3383a052216822fab1a37c8fe2794b0cdb/stl/inc/coroutine ). As you mentioned, symmetric transfer is the last remaining part – our compiler back-end dev Victor Tong has been working on that. We can’t promise anything yet, but it looks like it should be possible for symmetric transfer to be completed for 16.8 Preview 3 and the library feature-test macro updated accordingly; there is one known bug that will need to be fixed in Preview 4. If we encounter unexpected issues in the next few days this may change, hence the lack of guarantees.