C++14 STL Features, Fixes, And Breaking Changes In Visual Studio 14 CTP1

C++14 STL Features, Fixes, And Breaking Changes In Visual Studio 14 CTP1

Rate This
  • Comments 34

I'm Microsoft's STL maintainer, and once again we've got about a year's worth of work to tell you about.  ("We" means P.J. Plauger of Dinkumware for most features, myself for most fixes and Library Issue resolutions, plus fixes contributed by our libraries dev lead Artur Laksberg and our CRT maintainer James McNellis.)

 

If you missed the announcement, you can download VS14 CTP1 right now (pay attention to where they say "in a virtual machine, or on a computer that is available for reformatting"), and VS14 RTM "will most likely be available sometime in 2015".

 

Please note that in this post, I'm covering the changes between 2013 RTM and VS14 CTP1 - that is, the stuff listed here is what's new in VS14 CTP1.  (For example, N3656 "make_unique (Revision 1)" shipped in 2013 RTM, so it isn't listed here.)

 

Additionally, "CTP" stands for "Community Technology Preview" but it means "alpha".  Please report bugs through Microsoft Connect.

 

STL Features

We've implemented the following features which were voted into C++14, plus one Technical Specification:

 

N3642 <chrono>/<string> UDLs

N3644 Null Forward Iterators

N3654 quoted()

N3657 Heterogeneous Associative Lookup

N3658 integer_sequence

N3668 exchange()

N3670 get<T>()

N3671 Dual-Range equal()/is_permutation()/mismatch()

N3779 <complex> UDLs

N3887 tuple_element_t

N3940 Filesystem "V3" Technical Specification

 

Note that <complex>'s operator""if() overloads for imaginary floats were #if 0'ed due to missing compiler support.  (The problem is that "if" is a keyword.  C++14 says that when operator""if() is written without spaces, "if" won't be treated as a keyword, so it's okay.  Yeah, this is a wacky rule.)  The compiler was later fixed to support this special rule, so I've removed the #if 0 in my next batch of changes - but they haven't been checked in yet, so they aren't available in VS14 CTP1.

 

Also note that our <filesystem> V3 machinery is still being defined in V2's namespace std::tr2::sys.  That's because we did this work when N3803 (published October 2013) was the latest draft, and it specified a placeholder "to be determined" namespace std::tbd::filesystem.  The current draft N3940 (published March 2014) specifies std::experimental::filesystem::v1, and changing namespaces is on our todo list.

 

Furthermore, we've implemented the following Library Issue resolutions which were voted into C++14:

 

LWG 2097 packaged_task constructors should be constrained

LWG 2104 unique_lock move-assignment should not be noexcept

LWG 2112 User-defined classes that cannot be derived from

LWG 2144 Missing noexcept specification in type_index

LWG 2145 error_category default constructor

LWG 2162 allocator_traits::max_size missing noexcept

LWG 2174 wstring_convert::converted() should be noexcept

LWG 2176 Special members for wstring_convert and wbuffer_convert

LWG 2187 vector<bool> is missing emplace and emplace_back member functions

LWG 2193 Default constructors for standard library containers are explicit

LWG 2247 Type traits and std::nullptr_t

LWG 2268 Setting a default argument in the declaration of a member function assign of std::basic_string

LWG 2272 quoted should use char_traits::eq for character comparison

LWG 2278 User-defined literals for Standard Library types

LWG 2285 make_reverse_iterator

LWG 2306 match_results::reference should be value_type&, not const value_type&

LWG 2315 weak_ptr should be movable

LWG 2324 Insert iterator constructors should use addressof()

LWG 2329 regex_match()/regex_search() with match_results should forbid temporary strings

LWG 2332 regex_iterator/regex_token_iterator should forbid temporary regexes

LWG 2339 Wording issue in nth_element

LWG 2344 quoted()'s interaction with padding is unclear

LWG 2346 integral_constant's member functions should be marked noexcept

GB 9 Remove gets()

 

The story for noexcept is somewhat complicated.  We have internal _NOEXCEPT and _THROW0() macros (not for public consumption) which currently expand to "throw ()" (which in turn is treated by the compiler as a synonym for __declspec(nothrow), differing from C++98-14's Standard semantics for "throw ()").  These macros should expand to noexcept, but we've been prevented from doing so by a series of relatively minor compiler bugs, mostly involving C++14's rules for implicit noexcept on destructors.  (As the STL's implementation is inherently complex and widely used, it serves as a stringent test for compiler features.)  The good news is that these compiler bugs have been fixed, and I've been able to switch the STL's macros over to using real noexcept in my next batch of changes (with all of the STL's tests passing).  Unfortunately, this isn't available in VS14 CTP1.  (Additionally, we're still ironing out problems with conditional noexcept, which the STL is supposed to use in a few places.  Currently, our macros for that expand to nothing.)

 

As for gets(), which was removed from C11 and C++14 (note: C++14 still incorporates the C99 Standard Library, but has taken this change from C11 as a special exception), our CRT's <stdio.h> is still providing ::gets(), but our STL's <cstdio> is no longer providing std::gets().

 

We've also implemented an optimization, contributed by Eric Brumer from the compiler back-end team.  The compiler's autovectorization really loves highly-aligned memory, so we've changed std::allocator to automatically return highly-aligned memory for large allocations where it'll potentially make a difference in exchange for minimal overhead.  If you're curious, the magic numbers we're currently using are that we'll activate this special behavior for 4096-byte or larger allocations, and we'll align them to (at least) 32 bytes (256 bits), although we absolutely reserve the right to modify this in the future.  (Currently, we're doing this for x86 and x64, but not ARM - we haven't observed performance benefits due to over-alignment on that platform yet.)  Note that to avoid mismatch nightmares, this behavior cannot be disabled - it is activated regardless of whether you've asked the compiler to autovectorize, or even to emit AVX/etc. instructions at all.

 

STL Fixes

My introductory notes when I wrote about the STL fixes in VC 2013 continue to apply here.  Speaking of which, after I wrote that post, I was able to get a couple more fixes checked into 2013 RTM, but I never found the time to go back and update that post.  So for completeness, the following fixes shipped in 2013 RTM: std::bind() now calls std::tie() with qualification in order to avoid being confused by boost::tie() (DevDiv#728471/Connect#792163), and std::function's constructor now avoids crashing when out of memory (DevDiv#748972).

 

Additionally, we thought we had fixed the bug in iostreams where it was misparsing floating-point, but shortly before 2013 RTM we discovered a regression and reverted the change.  We're working on this again for VS14, but we're still aware of problems in this area.

 

Now, let's look at the fixes that are available in VS14 CTP1.  We've performed a couple of major overhauls:

 

* <chrono>'s clocks had several problems.  high_resolution_clock wasn't high resolution (DevDiv#349782/Connect#719443) and steady_clock and the CRT's clock() weren't steady (DevDiv#454551/Connect#753115).  We've fixed this by making high_resolution_clock a typedef for steady_clock (as permitted by the Standard), which is now powered by QueryPerformanceCounter(), which is high resolution and meets the Standard's requirements for steadiness/monotonicity.  As a result, steady_clock::time_point is now a typedef for chrono::time_point<steady_clock> (DevDiv#930226/Connect#858357), although strictly conformant code should not assume this.  (N3936 20.12.7.2 [time.clock.steady]/1 says that steady_clock::time_point is chrono::time_point<unspecified, chrono::duration<unspecified, ratio<unspecified, unspecified>>>.)  Independently, the CRT's clock() was reimplemented with QueryPerformanceCounter().  (Note that while this is a significant improvement, it still doesn't conform to the C Standard's requirement for clock() to return "processor time", which can advance slower or faster than one second per physical second depending on how many cores are being used.  Our CRT maintainer James McNellis believes that changing clock()'s behavior like that could break existing code - and for the record, I completely agree that this would be too scary to change.)  Additionally, we received a bug report about system_clock, asking whether it should return local time (time-zone-dependent) instead of UTC (DevDiv#756378).  The Standard is vague about this topic (20.12.7.1 [time.clock.system]/1 "Objects of class system_clock represent wall clock time from the system-wide realtime clock.", wow that's so helpful!).  Our implementation used GetSystemTimeAsFileTime(), which returns UTC.  After thinking about this issue, I concluded that UTC is strongly desirable here (programs should use UTC everywhere, performing time-zone adjustments for user I/O only).  I also checked with GCC/libstdc++ and clang/libc++'s maintainers, who confirmed that their implementations also return UTC.  So while I declined to change this behavior, I improved system_clock's implementation while I was in the neighborhood.  Now we call GetSystemTimePreciseAsFileTime() when it's available from the OS (Win8+), which has massively better resolution.  Note that the CRT/STL's OS-sensing behavior is automatic and requires no input from the user-programmer (i.e. it is not controlled by macros).

 

* <atomic>'s compiletime correctness, runtime correctness, and performance have been improved.  We've eradicated the last of our x86 inline assembly code, replacing it with intrinsics for improved performance.  (In these functions, the 8-byte atomics for x86, we're still an instruction or two away from being optimal, so we've requested new intrinsics from the compiler back-end team.)  We fixed a couple of runtime correctness bugs in the compare_exchange family of functions.  First, now we always perform the mapping specified by 29.6.5 [atomics.types.operations.req]/21 "When only one memory_order argument is supplied, the value of success is order, and the value of failure is order except that a value of memory_order_acq_rel shall be replaced by the value memory_order_acquire and a value of memory_order_release shall be replaced by the value memory_order_relaxed." (DevDiv#879907/Connect#817225).  Second, we fixed a bug in atomic<T *>'s compare_exchange where we were unconditionally writing to "expected" (DevDiv#887644/Connect#819819), while /21 says that the write must be conditional: "Atomically, compares the contents of the memory pointed to by object or by this for equality with that in expected, and if true, replaces the contents of the memory pointed to by object or by this with that in desired, and if false, updates the contents of the memory in expected with the contents of the memory pointed to by object or by this."  This fix also improved performance.  (Note that this was specific to atomic<T *>; atomic<integral> was unaffected.)  We also fixed several compiler errors.  Each atomic_meow is now a typedef for atomic<meow>, so "atomic_int atom(1729);" now compiles (DevDiv#350397/Connect#720151), and we fixed compiler errors in atomic<const T *> (DevDiv#829873/Connect#809351, DevDiv#879700/Connect#817201) and volatile atomic<T> (DevDiv#846428/Connect#811913).  Finally, we improved the performance of atomic construction - 29.6.5 [atomics.types.operations.req]/5 says "Initialization is not an atomic operation" but we were unnecessarily using atomic instructions for initialization.

 

Individual fixes in no particular order:

 

* C++11's minimal allocator interface is awesome, but it means that STL implementations have to do extra work in order to deal with user-defined allocators that lack portions of C++03's verbose allocator interface (e.g. nested rebind structs).  In 2013 RTM (thanks to variadic templates) we completed the machinery needed to adapt minimal allocators to the verbose interface, but we didn't consistently use it throughout the STL (DevDiv#781187/Connect#800709).  So for VS14 CTP1, we audited the entire STL and fixed all the problems, so now anything that takes an allocator will accept the minimal interface.  Notably, std::function, shared_ptr/allocate_shared(), and basic_string were fixed.

 

* Thanks to Filesystem V3, we now handle network paths of the form \\server\directory\filename.txt (DevDiv#512571/Connect#770316, DevDiv#706628/Connect#788976).

 

* <chrono>'s duration % duration, duration % rep, and duration / rep have been fixed to follow the Standard - previously they would fail to compile in various situations (DevDiv#742944/Connect#794649).

 

* The STL now supports the /Gv compiler option (/Gd, /Gr, and /Gz were already supported), as well as functions explicitly marked with __vectorcall (DevDiv#793009/Connect#804357).  We have a test to verify the former by including all STL headers under /Gv.  For the latter, __vectorcall will work wherever __stdcall/etc. works - which isn't everywhere (that's tracked by a separate bug, still active).

 

* The STL now supports the /Zc:strictStrings compiler option (DevDiv#784218).  C++03 permitted (but ISO-deprecated) conversions from string literals to modifiable char *.  C++11 removed this conversion, and /Zc:strictStrings enforces this prohibition.  While /Zc:strictStrings is currently off by default, I strongly encourage using it.

 

* In 2006, <locale>'s implementation was damaged in an obscure but extremely pernicious way, specific to x64 in debug mode (DevDiv#447546/Connect#750951, DevDiv#755427/Connect#796566).  With custom allocation functions (including globally replaced operator new/delete()), custom-allocated facets would be deallocated with free(), and then the world would explode.  I eventually figured out the full extent of the problem and thoroughly eradicated it forever.

 

* Working in conjunction with compiler fixes from Xiang Fan, we've changed the STL's headers to dramatically reduce object file sizes (and static library sizes) by avoiding the emission of unused machinery (DevDiv#888567/Connect#820750).  Such unused machinery was typically discarded by the linker, so EXE/DLL sizes should be unchanged (although they may experience minor improvements).  For example, when compiling a file (for x86 with /MD /O2) that includes all C and C++ Standard Library headers and does nothing else with them, VS 2013 emitted a 731 KB object file, while VS14 CTP1 emits less than 1 KB.

 

* C++11 requires STL implementations to tolerate overloaded address-of operators.  VS 2013's containers did, but not all of its algorithms (DevDiv#758134/Connect#797008).  Additionally, STL implementations are required to tolerate overloaded comma operators ("because nothing forbids them"), which is problematic for algorithms that take potentially-user-defined iterators and say things like "++iter1, ++iter2" in their for-loops (DevDiv#758138/Connect#797012).  We've audited all STL algorithms, with all permutations of iterator strengths, for address-of/comma issues.  We've fixed all of them (by adding a handful of addressof() calls and eleventy zillion (void) casts), and we've added a test to ensure that they stay fixed.

 

* Since 2005, we've shipped debug checks that detect and complain about invalid inputs to STL algorithms (like transposed iterators).  However, they've been slightly too aggressive, complaining about null pointers passed as iterators even when the Standard says that they're perfectly valid.  For example, merging two [null, null) ranges to a null output is a valid no-op.  We've audited every STL algorithm and fixed their debug checks to accept null pointers validly passed as iterators, while still rejecting invalid scenarios for null pointers.  (For example, [non-null, null) is a bogus range.)  This resolves long-standing bug reports (DevDiv#253803/Connect#683214, DevDiv#420517/Connect#741478, DevDiv#859062/Connect#813652).

 

* C++11's binary search algorithms are required to work with heterogeneous types, where the types of the range's elements and the given value can differ, and the range's elements might not even be comparable to each other.  We fixed lower_bound() and upper_bound() years ago, but missed equal_range() (DevDiv#813065/Connect#807044).  We left a C++03-era debug check in equal_range(), which was bad for two reasons: (1) it tried to verify that the input range was sorted, but C++11 doesn't require element < element to compile, and (2) this was a linear-time validation in a log-time algorithm which was always a bad idea!  We've removed the offending debug check, so equal_range() now conforms to C++11.  (However, equal_range() still contains another debug check.  lower_bound() is given only elem < value and upper_bound() is given only value < elem so they just have to trust that it's a valid comparison.  equal_range() requires both elem < value and value < elem to compile, so we can use our usual debug check to verify that they're never simultaneously true.  This is okay because the asymptotic complexity of the algorithm is unaffected.)

 

* We updated vector<bool>'s interface to conform to C++14, adding emplace(), emplace_back(), and a constructor from (count, alloc) (DevDiv#850453/Connect#812409, also LWG 2187).

 

* Our unordered associative containers didn't provide the strong guarantee for single-element insertion and rehashing as required by the Standard (DevDiv#732166).  Now they do.

 

* We fixed a spurious memory leak in std::locale reported by _CrtDumpMemoryLeaks() (DevDiv#846054).  Note that this wasn't a physical memory leak - our internal allocations were being freed correctly.  The problem was that they weren't being marked as "CRT-internal" which keeps them off of the _CrtDumpMemoryLeaks() radar.

 

* We fixed several problems in time_get's parsing, which affected "%I", "%p", "%S", "%T", and "%X" (DevDiv#821672/Connect#808162, DevDiv#836436, DevDiv#872926).

 

* codecvt now returns codecvt_base::partial when required by the Standard (DevDiv#653897/Connect#782724).

 

* User-defined allocators that marked functions like max_size() as virtual, triggered infinite recursion in our machinery for C++11 minimal allocators (DevDiv#819467/Connect#807914).  Because allocators aren't used polymorphically, there's no reason to mark their member functions as virtual, but nothing in the Standard forbids this.  We fixed our implementation to tolerate this scenario.

 

* <system_error>'s error_code/error_condition comparisons are now free functions as required by the Standard (DevDiv#833886/Connect#809821).

 

* Calling generic_category(), iostream_category(), system_category(), or future_category() from global destructors could crash (DevDiv#493504/Connect#765636).  We've reimplemented them using magic statics so that they can now be called at any time, by any number of threads, and they return "immortal" objects (until the binary is unloaded).

* <random>'s discrete_distribution(InIt, InIt) constructor was missing (DevDiv#850894/Connect#812538).  We've added this (also to its param_type), and verified that there weren't any other missing distribution constructors.

 

* <random>'s binomial_distribution::max() used to tell filthy lies (DevDiv#863998).  The lies have been carefully washed and autoclaved.

 

* <complex>'s proj() had a mistakenly repeated test and other incorrect behavior (DevDiv#494680/Connect#766093).  We've reimplemented it to conform to the Standard.

 

* regex format_default now follows ECMAScript exactly (DevDiv#821930).  In particular, "$" at the end of the string is now preserved, and "$0" and "$00" are now preserved unchanged (they aren't supposed to expand to the full match).  Additionally, we fixed a bug in format_sed's implementation, where mentioning bogus capture groups (like R"(\8)" when there is no eighth capture group) would crash.  We then verified that format_sed's implementation follows POSIX's rules - which are woefully underspecified (unlike ECMAScript), so when they're silent we follow GNU sed's behavior (e.g. R"(\0)" expands to the full match; this behavior is unchanged from 2013).

 

* As required by the Standard, when regex_match() and regex_search() are given match_results, they now always set ready() to true (DevDiv#822474).  Additionally, they now clear the match_results' contents before doing any work (this is observable if the match_results object is used for a successful match, and then reused for an unsuccessful match).

 

* regex used to crash when given self-referencing back-references, like R"(a(b\1)c)" (DevDiv#900202/Connect#829726).  Now it detects this and throws error_backref as required by the Standard.

 

* We fixed a bug where regex mishandled character classes like R"([\w\W])" which should match everything (DevDiv#658169).

 

* Previously, we've attempted to handle high-bit characters in <regex>, but [Normal-HighBit] character classes were still throwing error_range.  (This happened regardless of whether the high-bit character was escaped for C++, or escaped for regex.)  The Standard is annoyingly vague about the topic - the problem is that when chars are signed (as they are for VC; nobody should use the /J switch), [Normal-HighBit] ranges look like [Positive-Negative] which is the wrong order.  But high-bit support has been a popular user request, and apparently everybody expects high-bit characters to be interpreted as unsigned.  Therefore, we've changed our implementation accordingly, and we now believe that high-bit characters should work everywhere (DevDiv#723057/Connect#790783).

 

* We've overhauled to_string() and to_wstring() to conform to the Standard (DevDiv#835323/Connect#810452).  They now call the CRT, which has been separately improved to properly format infinities and large-but-finite floating-point numbers.

 

* stof() now performs range checking as required by the Standard (DevDiv#875295).  Instead of accepting values that are between the maximum float and maximum double (and converting them to float infinity), it now throws out_of_range.

 

* We fixed misleading comments in forward()'s implementation (DevDiv#881583/Connect#817356).

 

* One of forward()'s overloads was missing _NOEXCEPT, which we've added (DevDiv#928750/Connect#856528).  (See above for my explanation of the noexcept/_NOEXCEPT story.)

 

* We fixed a crash in debug mode when explicitly setting _ITERATOR_DEBUG_LEVEL to 1 (DevDiv#850534/Connect#812434).

 

* Including <math.h> and calling fabs(1) would fail to compile due to ambiguous overloads (DevDiv#864942).  We've fixed this by moving float/long double overloads out of <math.h> and into <cmath>, and then fixing remaining issues with <cmath>'s overloads/templates.  We now believe that this machinery conforms to the Standard.  (For those who are unfamiliar with this area, the <math.h>/<cmath> relationship is one of the biggest headaches in the Standard - ask any STL maintainer.)

 

* <typeinfo>'s implementation was incredibly complicated, and type_info::name() used the double-checked locking anti-pattern (DevDiv#575875).  (It's an anti-pattern without <atomic>, and this code definitely predated <atomic>.)  Multithreaded calls were actually observed to fail in practice, although this was rare.  We've dramatically simplified the implementation, and eradicated the multithreading bug.

 

* type_info's equality comparisons have been optimized (DevDiv#858581).  Now they perform a pointer comparison before a string comparison.

 

* Although packaged_task<T (Args)> was movable, packaged_task<T& (Args)> and packaged_task<void (Args)> weren't (DevDiv#725337/Connect#791185).  Now they're all movable.

 

* Default-constructed std::threads were returning garbage from native_handle() (DevDiv#861298/Connect#813946).  Now they return null handles, because that's what CreateThread() and _beginthreadex() return for failure.

 

* We've implemented the extremely subtle rule specified by 30.5.2 [thread.condition.condvarany]/5 "~condition_variable_any(); Requires: There shall be no thread blocked on *this. [ Note: That is, all threads shall have been notified; they may subsequently block on the lock specified in the wait. This relaxes the usual rules, which would have required all wait calls to happen before destruction. Only the notification to unblock the wait must happen before destruction. The user must take care to ensure that no threads wait on *this once the destructor has been started, especially when the waiting threads are calling the wait functions in a loop or using the overloads of wait, wait_for, or wait_until that take a predicate. -end note ]" (DevDiv#484720).

 

* We've improved mutex and condition_variable to avoid dynamically allocating memory in their constructors (DevDiv#578559/Connect#776596), although mutex's constructor still isn't constexpr (that's blocked on compiler support).

 

* Calling future::wait_for() on a deferred function returned by async(), before the deferred function has been invoked, now immediately returns future_status::deferred as required by the Standard (DevDiv#696045).

 

* packaged_task now abandons its shared state when required by the Standard (e.g. when destroyed) (DevDiv#831975/Connect#809632).

 

* futures obtained from async() with the launch::async policy now have blocking destructors as required by the Standard (DevDiv#836684/Connect#810623).

 

* Arendelle was trapped in deep, deep, deep, deep snow.  We've changed this winter weather and everything will be all right (Frozen#2013).

 

STL Breaking Changes (2013 RTM, Bonus Edition)

* LWG 2141 was voted into C++14 and implemented in 2013 RTM.  It makes common_type<T> use decay<T>.  This is a great improvement (as explained in the Library Issue), but it breaks people who thought they could use common_type<T> as an identity transformation (e.g. to inhibit template argument deduction).  Note that although VC's <type_traits> provides a non-Standard std::identity<T> struct (it's simultaneously a relic of the ancient STL and C++0x), it really shouldn't be used - its "const T& operator()(const T&) const" member function signature makes identity<void> invalid (because references to void can't be formed).  So if you need an identity struct, you should write your own.

 

STL Breaking Changes (VS14 CTP1)

(As usual, this isn't an exhaustive list, but it should cover the major issues you might encounter.)

 

* We now require allocator equality/inequality comparisons to accept const arguments on both sides.  (The Standard is vague about whether we're allowed to require this, but I believe that the Standardese is clearly defective here.)  This breaks code like "bool operator==(const MyAlloc& other)" which should be written as "bool operator==(const MyAlloc& other) const".

 

* The Standard has always forbidden containers of const elements (e.g. vector<const T>, set<const T>).  (C++98/03's prohibition was crystal clear: elements must be Assignable, which const T isn't.  C++11/14's prohibition is obscurely hidden, but it's there.)  Previously, VC accepted such containers due to non-Standard machinery in std::allocator.  We've removed that machinery, so such containers now fail to compile.

 

* Filesystem V3's interface is significantly different from V2's (shipped in 2013 and earlier).  Very simple code will continue to work (because we haven't changed the namespace), but more complicated code will fail to compile.

 

* If you define _USE_32BIT_TIME_T, you are bad, you should feel bad, and the STL will now emit "#error 32-bit time_t is strongly deprecated and can trigger crashes in the C++ Standard Library.".

 

* Previously, std::allocator::deallocate(p, n) ignored n.  The Standard has always required that "n shall equal the value passed as the first argument to the invocation of allocate which returned p" (20.7.9.1 [allocator.members]/8), and we now need to inspect n for the over-alignment optimization that was described above.  Code that was passing bogus values for n may now crash.

 

* As a reminder, STL headers are allowed to include each other in unspecified ways.  (There are some cases in which header X is mandated to include header Y.)  Every release, we make changes to our include structure (sometimes we need more stuff available, sometimes we don't need stuff anymore).  Therefore, user code should be written so that it carefully includes all of the headers that it needs according to the Standard - this makes code portable across versions and platforms.  I'm aware of two header changes that have affected user code.  First, <string> no longer drags in <iterator>.  Second, <tuple> now declares std::array (without dragging in all of <array>, although it would be permitted to), which can and has broken code through the following chain of events: someone has a variable named "array", and they've got a using-directive "using namespace std;", and they're including an STL header (e.g. <functional>) that drags in <tuple> which now declares std::array.

 

STL Breaking Changes (VS14 Post-CTP1)

It's too early to talk about what'll be in VS14's STL after CTP1 (not because I'm forbidden from doing so - I'm simply cautious when it comes to talking about things that haven't been checked into source control yet), but I've accumulated a couple months' worth of edits which contain a couple of breaking changes that I should probably talk about sooner rather than later.

 

* In VS14, we're going to deprecate <hash_map> and <hash_set>.  Including them will emit a static_assert of the form "<hash_map> is deprecated and will be REMOVED. Please use <unordered_map>. You can define _SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS to acknowledge that you have received this warning."  (I reserve the right to change that macro name before RTM, although I like what I've got.)  Defining the escape hatch macro (one macro works for both headers) will allow your code to compile, and the containers will be fully supported in VS14 aside from this frowny face.  Then in VS15, these headers will be REMOVED FOREVER.  They're a maintenance burden - the underlying machinery that powers hash_meow and unordered_meow has to be more complicated in order to support two flavors.  The pre-Standardization hash_meow interface is also more difficult to use than the Standard unordered_meow interface.

 

We considered doing clever things like making hash_meow an alias template for unordered_meow, but because their interfaces differ (primarily in how they accept custom hashes), that could lead to complicated build breaks.  We believe that an impossible-to-ignore deprecation message, followed by outright removal, is the simplest and safest transition strategy.  In general, a hash_meow container can be easily replaced with unordered_meow, it's just that a human programmer should observe the process (converting any custom hashes if necessary).

 

* Additionally, we're reworking the STL's empty allocator/comparator/hasher/predicate optimization to improve conformance and performance.  As a result, the STL's associative containers (the <map> family) will require their comparators to have const-callable function call operators.  That is, "bool operator()(const X& a, const X& b)" will fail to compile, and will have to be changed to "bool operator()(const X& a, const X& b) const".  The Standard is (surprisingly!) unclear on the requirements for comparators here, and other STL implementations differ about what they accept.  I've brought this up on the Committee's mailing list, and there was a general feeling that comparators should be required to be const-invokable.  I plan to file a Library Issue in the future about this.

 

Frequently Asked Questions

Q1: Can we get these features and fixes in a 2013 Update?

 

A1: I'm sorry, but the answer is still no.  Please see Q4 and Q5 in last year's post.

 

Q2: Can we get tables listing the compiler/library features in VS14 CTP1?

 

A2: Yep!  (I've got a spreadsheet for C++14 Library features and issues, whereas I didn't have one for C++11.)  I'll post them in the very near future, probably early next week.

 

Thanks again for reading my long posts.  Please try out CTP1 (in a VM!) and let us know what you think.

 

Stephan T. Lavavej

Senior Developer - Visual C++ Libraries

stl@microsoft.com

  • Awesome work! Yes, a backport would be awesome, but at least there's a good explanation in the A1 link. Time to enjoy the sun and open up the gates now.

  • Oh, I'm such a fool, facets can't be free()d! No escape from the bugs inside of me!

  • > the Standard unordered_meow interface

    Hmmm, must have missed that in the documentation ...

  • Hey STL, have you guys considered making an allow_zero_sized [[attribute]] or __declspec that 0 sized objects to be sizeof(0)?

    This way all these 0 sized object optimizations become trivial to write:

    template<class T, class A>

    class vector {

    [[allow_zero_sized]]

    A allocator_;

    T *begin_;

    };

    sizeof(vector::allocator_) is allowed to be 0 and share the same address as vector::begin_ if it has no members.

  • Great stuff!

    However, is this confirmed as a compiler bug and would be potentially fixed in 14?

    connect.microsoft.com/.../visual-c-2013-rtm-with-update-1-initializer-list-bug

    (The same still fails to compile under Visual Studio 2013 with Update 3 CTP, and I wasn't able to install 14 side by side).

  • asdf: I would love a simpler mechanism (my _Compressed_pair machinery is somewhat invasive), but I am not convinced that attributes would be the right thing to use.

    Lin: First, there was a "temporaries in initializer lists are getting destroyed too early" compiler bug that was fixed in 2013 Update 2.  But your repro is a little different - you have an Element that contains a list<Element>. At that point, Element is incomplete, so the Standard technically forbids making a container of that type. You may be able to get away with it for list (our deque would explode) but it's still nonconformant, and it may be triggering the unexpected behavior here. Can you get initializer lists to misbehave without involving "recursive types" like that?

  • Bread?  WHat is if with spaces?  What is if withouth spaces?  As in, look like.

  • What will happen now with XP compatibility? On one hand, there is a v140_xp platform toolset.

    On the other hand, it doesn't work, because the new runtime dlls depend on Win2003 and Vista-specific imports.

    Will this be fixed, or the xp toolset is going away?

  • Hi STL -

    Wonderful to see such progress towards C++11 conformance. A few questions:

    - Will we ever see a conforming implementation of std::list::splice? Up to VS2013, the implementation of std::list::splice invalidates some iterators: msdn.microsoft.com/.../72fb8wzd.aspx, but my understanding of [23.3.5.5] requires that all iterators and references remain valid after splice. Given that the ability to efficiently splice is one of the primary reasons to ever use list in practice, a lack of conformance here is troublesome.

    - Will we ever see a bumped value for __cplusplus? To 201103L? To 201402L?  I understand the reasons for not bumping before full conformance, but I want to know if it will be set even once you do reach, say, C++11 conformance (mod bugs), or whether it will always be unreliable. I ask because a codebase that is attempting to transition to C++11 by way of #ifdef blocks based on __cplusplus currently cannot capitalize on any C++11 features when using the MS compilers.

    - Based on the table here: blogs.msdn.com/.../first-preview-of-visual-studio-quot-14-quot-available-now.aspx, the only C++11 (or older) features still missing are expression SFINAE, C++11 pre-processor, and C++98 (!) two-phase lookup. While these are all somewhat exotic, can we reasonably expect to see motion here soon, so that we can have a real C++11 toolchain on Windows? I'd much prefer that to any C++14 feature.

    Thanks,

    acm

  • Azarien> What will happen now with XP compatibility?

    The current plan of record is that VS14 RTM will support XP targeting. However, management may change the plan. My PERSONAL opinion is that it's time to cut XP targeting (it's burdensome and has been causing headaches for improving mutex/condition_variable): XP is out of support, Server 2003 is out of support on July 14, 2015, and even XP Embedded is out of support on Jan 12, 2016. Again in my PERSONAL opinion, given that VS14 RTM is planned for 2015, then it takes some time for user-programmers to upgrade, then more time for them to ship their programs to end users, I think it's clearly time (user-programmers who want to target out-of-support OSes can continue to use VS 2013 while it's supported). But I don't get to make the decision.

    andrewcmorrow> Will we ever see a conforming implementation of std::list::splice?

    I fixed this in 2013 RTM. Read last year's post where I said: "C++11 says that list::splice() doesn't invalidate iterators, it just transfers the affected iterators (DevDiv#671816/Connect#785388).  This is a physical guarantee, but our debug checks considered such iterators to be invalidated.  We've updated the checks so they rigorously follow C++11's rules.  (Note: forward_list::splice_after() is still affected; we plan to fix this in the future, but not in 2013 RTM.)"

    I still haven't gotten a chance to fix forward_list::splice_after (it differs in several significant ways), but as forward_list is the STL's least useful container I consider this to be low priority.

  • > Will we ever see a bumped value for __cplusplus?

    My psychic powers tell me that users would scream if we bumped the value without all features implemented. Once all C++11 features are implemented, I see nothing that would stop us from updating the value.

    > Based on the table here

    That's not an exhaustive table. See blogs.msdn.com/.../c-11-14-core-language-features-in-vs-2013-and-the-nov-2013-ctp.aspx for my exhaustive table (following GCC's, so it lists some library features in the Concurrency section). I will be publishing an updated table for VS14 CTP1 as I mentioned in Q2 here. For example, attributes and char16_t/char32_t are still unimplemented (also, C++98-14's dynamic exception specifications; they are now ISO-deprecated but still Standard).

    > can we reasonably expect to see motion here soon, so that we can have a real C++11 toolchain on Windows?

    Please remember that I'm neither a compiler dev nor a manager, and I have to be careful when talking about future plans, the work of other teams, and especially the future plans of other teams. That said, we've previously announced that the compiler team does intend to reach full C++03 (minus export, good riddance) and C++11 conformance, but they will also implement C++14 features ahead of older features based on importance to users and difficulty of implementation. See Q2 in last year's post. Expression SFINAE is particularly important because the STL needs it, but it is also particularly difficult in the compiler's current codebase (which, as I have let slip in the past, lacks a complete AST).

  • From this blog: blogs.msdn.com/.../c99-library-support-in-visual-studio-2013.aspx posted last year:

    /quote

    > We know that this is not complete support for the C99 library functions. To the best of our understanding, the missing pieces are these:

    •The tgmath.h header is missing. C compiler support is needed for this header.

    ◦Note that the ctgmath header was added—this is possible because that header does not require the tgmath.h header—only the ccomplex and cmath headers.

    •The uchar.h header is missing. This is from the C Unicode TR.

    •Several format specifiers in the printf family are not yet supported.

    •The snprintf and snwprintf functions are missing from stdio.h and wchar.h.

    /unquote

    Is it correct to deduce that:

    - last two are incorporated?

    - The only headers missing in VS2014 for C99 standard are: tgmath.h and uchar.h and other than these C99 support is complete?

    When would the tgmath.h be incorporated in VS world and we close C99 chapter once forever?

    @STL, thank you 1Million times from every VC developer; for all the efforts you are have done and planning on doing. Same goes for rest of the league! <3 <3 <3

  • You're welcome, Tony! I believe your understanding is correct, but note that (1) this is limited to the C99 Standard Library, not the C99 Core Language (which 2013 partially supports), and (2) James is the authority here and is preparing a post for next week detailing the CRT changes.

    > When would the tgmath.h be incorporated in VS world and we close C99 chapter once forever?

    That would require compiler changes; I am not aware of any plans for that. (Note that tgmath.h is superfluous for C++.)

  • @STL, oh no! So it means we can't still just go to github and download any C project and compile with VS !!

    I wonder how long it will take VS to eventually get there !!!

    Please ask James to shed light on which language features are implemented and which are missing, separate from "language standard".

    Thanks.

  • (I am not sure if you can comment on this compiler question, but I am asking anyway.. perhaps you can ask the suitable person to reply!)

    Since constexpr is a sublanguage within C++, would there be a separate AST for constexpr? I am not expert but I have a feeling that it will make lot of sense to maintain its AST separately.. :)

Page 1 of 3 (34 items) 123