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.

14 comments

Leave a comment