In VS 2015 Update 2, we’ve implemented every C++ Standard Library feature that’s been voted into C++11, C++14, and the C++17-so-far Working Paper N4567. (See the end of this post for Update 2 availability information.) Here’s the table:
Status |
Std |
Paper |
Title |
Update 2 |
C++14 |
SFINAE-Friendly result_of |
|
Update 2 |
C++17 |
Improving pair And tuple |
|
Up2 Win7+ |
C++17 |
shared_mutex (Untimed) |
|
Up2 opt-in |
C++17 |
Removing Deprecated Iostreams Aliases |
|
Update 2 |
C++17 |
Variable Templates For Type Traits (is_same_v, etc.) |
|
Update 2 |
C++17 |
as_const() |
|
Update 2 |
C++17 |
Logical Operator Type Traits (conjunction, etc.) |
|
Update 2 |
C++17 |
owner_less<> |
|
Update 2 |
C++17 |
<chrono> floor(), ceil(), round(), abs() |
|
Update 2 |
C++17 |
Variadic lock_guard |
|
VS 2015 |
C++14 |
constexpr For <complex> |
|
VS 2015 |
C++14 |
constexpr For <chrono> |
|
VS 2015 |
C++14 |
constexpr For <array> |
|
VS 2015 |
C++14 |
constexpr For <initializer_list>, <tuple>, <utility> |
|
VS 2015 |
C++14 |
integral_constant::operator()() |
|
VS 2015 |
C++14 |
UDLs For <chrono>, <string> (1729ms, “meow”s, etc.) |
|
VS 2015 |
C++14 |
Null Forward Iterators |
|
VS 2015 |
C++14 |
quoted() |
|
VS 2015 |
C++14 |
Heterogeneous Associative Lookup |
|
VS 2015 |
C++14 |
integer_sequence |
|
VS 2015 |
C++14 |
shared_mutex (Timed) |
|
VS 2015 |
C++14 |
exchange() |
|
VS 2015 |
C++14 |
Fixing constexpr Member Functions Without const |
|
VS 2015 |
C++14 |
get<T>() |
|
VS 2015 |
C++14 |
Dual-Range equal(), is_permutation(), mismatch() |
|
VS 2015 |
C++14 |
Sized Deallocation |
|
VS 2015 |
C++14 |
UDLs For <complex> (3.14i, etc.) |
|
VS 2015 |
C++14 |
constexpr For <functional> |
|
VS 2015 |
C++14 |
tuple_element_t |
|
VS 2015 |
C++14 |
Renaming shared_mutex (Timed) To shared_timed_mutex |
|
VS 2015 |
C++17 |
void_t |
|
VS 2015 |
C++17 |
Safe Conversions In unique_ptr<T[]> |
|
VS 2015 |
C++17 |
invoke() |
|
2015 opt-in |
C++17 |
Removing auto_ptr, random_shuffle(), And Old <functional> Stuff |
|
VS 2015 |
C++17 |
noexcept Cleanups |
|
VS 2015 |
C++17 |
uncaught_exceptions() |
|
VS 2015 |
C++17 |
Trivially Copyable reference_wrapper |
|
VS 2015 |
C++17 |
insert_or_assign()/try_emplace() For map/unordered_map |
|
VS 2015 |
C++17 |
size(), empty(), data() |
|
VS 2015 |
C++17 |
Precisely Constraining unique_ptr Assignment |
|
VS 2015 |
C++17 |
bool_constant |
|
VS 2013 |
C++14 |
Minimal Container Element Requirements |
|
VS 2013 |
C++14 |
Transparent Operator Functors (less<>, etc.) |
|
VS 2013 |
C++14 |
Alias Templates For <type_traits> (decay_t, etc.) |
|
VS 2013 |
C++14 |
make_unique() |
|
VS 2013 |
C++17 |
Supporting Incomplete Types In vector/list/forward_list |
|
N/A |
C++14 |
Discouraging rand() |
|
N/A |
C++17 |
Contiguous Iterators |
“N/A” means that these proposals altered the Standard’s wording, but did not physically affect implementers or users. I’ve listed them as Not Applicable for the sake of completeness.
We previously announced that compiler support for Expression SFINAE became Partial in Update 1. While it’s still Partial in Update 2, the compiler team was able to improve it to the point where the STL could carefully take a dependency on it. As a result, Update 2’s STL fully supports N3462 “SFINAE-Friendly result_of” and LWG 2132 “std::function ambiguity”. This is verified by exhaustive unit tests that run for every build. (LWG 2132 allows meow(function<void (int)>) and meow(function<void (int, int)>) to be overloaded, then meow() can be called with a lambda taking 1 or 2 ints, and the corresponding overload will be selected.)
A notable consequence of N4387 “Improving pair And tuple” is that tuples can now be brace-returned when it’s safe to do so. For example, { “cute”, “fluffy”, “kittens” } can be returned as tuple<string, string, string>, because std::string has an implicit constructor from const char *.
N4508 “shared_mutex (Untimed)” isn’t supported on XP/Vista-class OSes (both client and server). This is because our implementation of std::shared_mutex wraps SRWLOCK, and requires OS APIs that were introduced in Win7-class OSes. Like std::forward_list, the whole purpose of std::shared_mutex is to offer lower overhead at the cost of reduced functionality. Attempting to support XP/Vista with dynamic checks would compromise std::shared_mutex’s reason for existing. If you require XP/Vista support, you should use std::shared_timed_mutex, which offers strictly greater functionality.
P0004R1 “Removing Deprecated Iostreams Aliases” is opt-in. If you define _HAS_OLD_IOSTREAMS_MEMBERS to 0 project-wide, we’ll remove this old machinery (which was “born deprecated” in C++98). Similarly, LWG 2385 “function::assign allocator argument doesn’t make sense” is requested by defining _HAS_FUNCTION_ASSIGN to 0 project-wide, and N4190 “Removing auto_ptr, random_shuffle(), And Old <functional> Stuff” is requested by defining _HAS_AUTO_PTR_ETC to 0 project-wide. In future major versions, we intend to make these removals opt-out and then unconditional.
Now, I should mention some caveats. “Feature complete” doesn’t mean “literally every electron in the Standard”. We’re still missing a few things that are smaller than entire proposals:
* A very small number of constexpr occurrences are missing. The exhaustive list is: in C++11, mutex’s default constructor requires a major representation change (which we can’t ship in an Update). In C++14, error_category’s default constructor requires a minor representation change (also forbidden in 2015 Updates, but already fixed for the next major version). Finally, C++14’s min()/max()/minmax() for initializer_list and C++17’s min_element()/max_element()/minmax_element() inherently contain loops, so they require C++14 extended constexpr support from the compiler, which is not yet available.
* Our C99 Standard Library implementation is complete, except for tgmath.h (which is irrelevant in C++) and the CX_LIMITED_RANGE/FP_CONTRACT pragma macros.
* We’ve made substantial progress in implementing C++14/17’s Library Issue resolutions (see table below; Library Issues are bugs in the Standard itself), but 8 Library Issues fixed in C++14 and 11 Library Issues fixed in C++17-so-far remain to be implemented.
* More features will inevitably be voted into C++17 before its final publication, but we’re caught up as of this very moment.
* There are still bugs, which we’re working on fixing. (We’ve fixed approximately 36 STL bugs in Update 2 so far. I’ll post a changelog for the final release of Update 2.)
Here’s our Library Issue table:
Status |
Std |
Title |
|
Update 2 |
C++14 |
LWG 2005 |
unordered_map::insert(T&&) protection should apply to map too |
Update 2 |
C++14 |
LWG 2021 |
Further incorrect usages of result_of |
Update 2 |
C++14 |
LWG 2132 |
std::function ambiguity |
Update 2 |
C++14 |
LWG 2196 |
Specification of is_*[copy/move]_[constructible/assignable] unclear for non-referencable types |
Update 2 |
C++17 |
LWG 2101 |
Some transformation types can produce impossible types |
Update 2 |
C++17 |
LWG 2106 |
move_iterator wrapping iterators returning prvalues |
Update 2 |
C++17 |
LWG 2127 |
Move-construction with raw_storage_iterator |
Update 2 |
C++17 |
LWG 2217 |
operator==(sub_match, string) slices on embedded ”s |
Update 2 |
C++17 |
LWG 2353 |
std::next is over-constrained |
Update 2 |
C++17 |
LWG 2354 |
Unnecessary copying when inserting into maps with braced-init syntax |
Update 2 |
C++17 |
LWG 2367 |
pair and tuple are not correctly implemented for is_constructible with no args |
Up2 opt-in |
C++17 |
LWG 2385 |
function::assign allocator argument doesn’t make sense |
Update 2 |
C++17 |
LWG 2455 |
Allocator default construction should be allowed to throw |
Update 2 |
C++17 |
LWG 2466 |
allocator_traits::max_size() default behavior is incorrect |
Update 2 |
C++17 |
LWG 2469 |
Wrong specification of Requires clause of operator[] for map and unordered_map |
Update 2 |
New |
LWG 2549 |
Tuple EXPLICIT constructor templates […] will create dangling references |
missing |
C++14 |
LWG 2064 |
More noexcept issues in basic_string |
missing |
C++14 |
LWG 2078 |
Throw specification of async() incomplete |
missing |
C++14 |
LWG 2135 |
Unclear requirement for exceptions thrown in condition_variable::wait() |
missing |
C++14 |
LWG 2140 |
notify_all_at_thread_exit synchronization |
missing |
C++14 |
LWG 2203 |
scoped_allocator_adaptor uses wrong argument types for piecewise construction |
missing |
C++14 |
LWG 2210 |
Missing allocator-extended constructor for allocator-aware containers |
missing |
C++14 |
LWG 2252 |
Strong guarantee on vector::push_back() still broken with C++11? |
missing |
C++14 |
LWG 2350 |
min, max, and minmax should be constexpr |
missing |
C++17 |
LWG 1169 |
num_get not fully compatible with strto* |
missing |
C++17 |
LWG 2059 |
C++0x ambiguity problem with map::erase |
missing |
C++17 |
LWG 2063 |
Contradictory requirements for string move assignment |
missing |
C++17 |
LWG 2156 |
Unordered containers’ reserve(n) reserves for n-1 elements |
missing |
C++17 |
LWG 2219 |
INVOKE-ing a pointer to member with a reference_wrapper as the object expression |
missing |
C++17 |
LWG 2369 |
constexpr max(initializer_list) vs max_element |
missing |
C++17 |
LWG 2408 |
SFINAE-friendly common_type / iterator_traits is missing in C++14 |
missing |
C++17 |
LWG 2415 |
Inconsistency between unique_ptr and shared_ptr |
missing |
C++17 |
LWG 2439 |
unique_copy() sometimes can’t fall back to reading its output |
missing |
C++17 |
LWG 2476 |
scoped_allocator_adaptor is not assignable |
missing |
C++17 |
LWG 2485 |
get() should be overloaded for const tuple&& |
VS 2015 |
C++14 |
GB 9 |
Remove gets from C++14 |
VS 2015 |
C++14 |
LWG 2009 |
Reporting out-of-bound values on numeric string conversions |
VS 2015 |
C++14 |
LWG 2094 |
duration conversion overflow shouldn’t participate in overload resolution |
VS 2015 |
C++14 |
LWG 2097 |
packaged_task constructors should be constrained |
VS 2015 |
C++14 |
LWG 2103 |
std::allocator_traits<std::allocator<T>>::propagate_on_container_move_assignment |
VS 2015 |
C++14 |
LWG 2104 |
unique_lock move-assignment should not be noexcept |
VS 2015 |
C++14 |
LWG 2112 |
User-defined classes that cannot be derived from |
VS 2015 |
C++14 |
LWG 2144 |
Missing noexcept specification in type_index |
VS 2015 |
C++14 |
LWG 2145 |
error_category default constructor |
VS 2015 |
C++14 |
LWG 2162 |
allocator_traits::max_size missing noexcept |
VS 2015 |
C++14 |
LWG 2174 |
wstring_convert::converted() should be noexcept |
VS 2015 |
C++14 |
LWG 2176 |
Special members for wstring_convert and wbuffer_convert |
VS 2015 |
C++14 |
LWG 2187 |
vector<bool> is missing emplace and emplace_back member functions |
VS 2015 |
C++14 |
LWG 2193 |
Default constructors for standard library containers are explicit |
VS 2015 |
C++14 |
LWG 2247 |
Type traits and std::nullptr_t |
VS 2015 |
C++14 |
LWG 2268 |
Setting a default argument in the declaration of a member function assign of std::basic_string |
VS 2015 |
C++14 |
LWG 2272 |
quoted should use char_traits::eq for character comparison |
VS 2015 |
C++14 |
LWG 2275 |
Why is forward_as_tuple not constexpr? |
VS 2015 |
C++14 |
LWG 2278 |
User-defined literals for Standard Library types |
VS 2015 |
C++14 |
LWG 2280 |
begin / end for arrays should be constexpr and noexcept |
VS 2015 |
C++14 |
LWG 2285 |
make_reverse_iterator |
VS 2015 |
C++14 |
LWG 2301 |
Why is std::tie not constexpr? |
VS 2015 |
C++14 |
LWG 2306 |
match_results::reference should be value_type&, not const value_type& |
VS 2015 |
C++14 |
LWG 2315 |
weak_ptr should be movable |
VS 2015 |
C++14 |
LWG 2324 |
Insert iterator constructors should use addressof() |
VS 2015 |
C++14 |
LWG 2329 |
regex_match()/regex_search() with match_results should forbid temporary strings |
VS 2015 |
C++14 |
LWG 2332 |
regex_iterator/regex_token_iterator should forbid temporary regexes |
VS 2015 |
C++14 |
LWG 2339 |
Wording issue in nth_element |
VS 2015 |
C++14 |
LWG 2344 |
quoted()’s interaction with padding is unclear |
VS 2015 |
C++14 |
LWG 2346 |
integral_constant’s member functions should be marked noexcept |
VS 2015 |
C++17 |
LWG 2129 |
User specializations of std::initializer_list |
VS 2015 |
C++17 |
LWG 2133 |
Attitude to overloaded comma for iterators |
VS 2015 |
C++17 |
LWG 2212 |
tuple_size for const pair request header |
VS 2015 |
C++17 |
LWG 2234 |
assert() should allow usage in constant expressions |
VS 2015 |
C++17 |
LWG 2365 |
Missing noexcept in shared_ptr::shared_ptr(nullptr_t) |
VS 2015 |
C++17 |
LWG 2399 |
shared_ptr’s constructor from unique_ptr should be constrained |
VS 2015 |
C++17 |
LWG 2400 |
shared_ptr’s get_deleter() should use addressof() |
VS 2015 |
C++17 |
LWG 2401 |
std::function needs more noexcept |
VS 2015 |
C++17 |
LWG 2403 |
stof() should call strtof() and wcstof() |
VS 2015 |
C++17 |
LWG 2407 |
packaged_task(allocator_arg_t, const Allocator&, F&&) should neither be constrained nor explicit |
VS 2015 |
C++17 |
LWG 2420 |
function<void(ArgTypes…)> does not discard the return value of the target object |
VS 2015 |
C++17 |
LWG 2433 |
uninitialized_copy()/etc. should tolerate overloaded operator& |
VS 2015 |
C++17 |
LWG 2440 |
seed_seq::size() should be noexcept |
VS 2015 |
C++17 |
LWG 2442 |
call_once() shouldn’t DECAY_COPY() |
VS 2015 |
C++17 |
LWG 2454 |
Add raw_storage_iterator::base() member |
VS 2015 |
C++17 |
LWG 2458 |
N3778 and new library deallocation signatures |
VS 2015 |
C++17 |
LWG 2464 |
try_emplace and insert_or_assign misspecified |
VS 2015 |
C++17 |
LWG 2467 |
is_always_equal has slightly inconsistent default |
VS 2015 |
C++17 |
LWG 2483 |
throw_with_nested() should use is_final |
VS 2015 |
C++17 |
LWG 2484 |
rethrow_if_nested() is doubly unimplementable |
VS 2015 |
C++17 |
LWG 2486 |
mem_fn() should be required to use perfect forwarding |
VS 2015 |
C++17 |
LWG 2487 |
bind() should be const-overloaded, not cv-overloaded |
VS 2015 |
C++17 |
LWG 2488 |
Placeholders should be allowed and encouraged to be constexpr |
VS 2015 |
C++17 |
LWG 2489 |
mem_fn() should be noexcept |
VS 2013 |
C++14 |
LWG 1214 |
Insufficient/inconsistent key immutability requirements for associative containers |
VS 2013 |
C++14 |
LWG 2011 |
Unexpected output required of strings |
VS 2013 |
C++14 |
LWG 2018 |
regex_traits::isctype Returns clause is wrong |
VS 2013 |
C++14 |
LWG 2033 |
Preconditions of reserve, shrink_to_fit, and resize functions |
VS 2013 |
C++14 |
LWG 2039 |
Issues with std::reverse and std::copy_if |
VS 2013 |
C++14 |
LWG 2047 |
Incorrect “mixed” move-assignment semantics of unique_ptr |
VS 2013 |
C++14 |
LWG 2049 |
is_destructible is underspecified |
VS 2013 |
C++14 |
LWG 2050 |
Unordered associative containers do not use allocator_traits to define member types |
VS 2013 |
C++14 |
LWG 2056 |
future_errc enums start with value 0 (invalid value for broken_promise) |
VS 2013 |
C++14 |
LWG 2061 |
make_move_iterator and arrays |
VS 2013 |
C++14 |
LWG 2067 |
packaged_task should have deleted copy c’tor with const parameter |
VS 2013 |
C++14 |
LWG 2074 |
Off by one error in std::reverse_copy |
VS 2013 |
C++14 |
LWG 2083 |
const-qualification on weak_ptr::owner_before |
VS 2013 |
C++14 |
LWG 2087 |
iostream_category() and noexcept |
VS 2013 |
C++14 |
LWG 2096 |
Incorrect constraints of future::get in regard to MoveAssignable |
VS 2013 |
C++14 |
LWG 2128 |
Absence of global functions cbegin/cend |
VS 2013 |
C++14 |
LWG 2138 |
atomic_flag::clear ordering constraints |
VS 2013 |
C++14 |
LWG 2141 |
common_type trait produces reference types |
VS 2013 |
C++14 |
LWG 2143 |
ios_base::xalloc should be thread-safe |
VS 2013 |
C++14 |
LWG 2148 |
Hashing enums should be supported directly by std::hash |
VS 2013 |
C++14 |
LWG 2188 |
Reverse iterator does not fully support targets that overload operator& |
VS 2013 |
C++14 |
LWG 2197 |
Specification of is_[un]signed unclear for non-arithmetic types |
VS 2013 |
C++14 |
LWG 2213 |
Return value of std::regex_replace |
VS 2013 |
C++14 |
LWG 2229 |
Standard code conversion facets underspecified |
VS 2013 |
C++14 |
LWG 2284 |
Inconsistency in allocator_traits::max_size |
VS 2013 |
C++14 |
LWG 2293 |
Wrong facet used by num_put::do_put |
VS 2013 |
C++14 |
LWG 2313 |
tuple_size should always derive from integral_constant |
VS 2013 |
C++14 |
LWG 2317 |
The type property queries should be UnaryTypeTraits returning size_t |
VS 2013 |
C++14 |
LWG 2330 |
regex(“meow”, regex::icase) is technically forbidden but should be permitted |
VS 2013 |
C++14 |
LWG 2341 |
Inconsistency between basic_ostream::seekp(pos) and basic_ostream::seekp(off, dir) |
VS 2013 |
C++14 |
LWG 2359 |
How does regex_constants::nosubs affect basic_regex::mark_count()? |
VS 2013 |
C++14 |
LWG 2360 |
reverse_iterator::operator*() is unimplementable |
VS 2013 |
C++17 |
LWG 2244 |
Issue on basic_istream::seekg |
VS 2013 |
C++17 |
LWG 2273 |
regex_match ambiguity |
VS 2013 |
C++17 |
LWG 2473 |
basic_filebuf’s relation to C FILE semantics |
I’ve omitted 125 N/A issues, which require no action from implementers as far as I can tell.
One issue here is special. The Proposed Resolution for LWG 2549 “Tuple EXPLICIT constructor templates […] will create dangling references” hasn’t been voted into C++17 yet, but I implemented it and listed it here because it’s required to implement C++17’s N4387 “Improving pair And tuple” safely.
Frequently Asked Questions
Q: Argh, you’re implementing C++17 library features before finishing C++11 compiler features.
A: That’s not a question.
Q: Whyyyy?
A: Much better. There are at least two reasons. First, library devs aren’t interchangeable with compiler devs. The library and compiler codebases are totally different, and while we’re all advanced C++ programmers, the required skillsets for library vs. compiler development are non-overlapping to a much greater extent than most people appreciate. It’s very rare for someone to work on both (Gor Nishanov is a notable exception; he’s been adding support for await to both). The effort that’s going into the STL isn’t being withheld from the compiler, really! Second, STL development exercises/stresses compiler features, making the compiler more robust. Several examples: implementing C++14 result_of/function SFINAE in the STL led to improvements in the compiler’s ongoing implementation of C++11 Expression SFINAE (pointer-to-data-member expressions were especially tricky), implementing C++11/14/17 occurrences of constexpr throughout the STL led to numerous improvements in the compiler’s support for C++11 constexpr, and implementing C++17’s pair/tuple changes (which involved a novel use of SFINAE in the STL) identified numerous compiler bugs that are being worked on. So, all of this STL work is indirectly making the compiler better, especially for code that behaves like the STL (e.g. Boost).
Q: What’s new in the compiler?
A: We’ll publish an updated feature table for the compiler, but the changes since RTM are that Expression SFINAE is Partial in Update 1, and Variable Templates are Yes in Update 2 (and are used by the STL’s is_same_v/etc.). However, support for variable templates is restricted to C1XX and Clang, the compiler front-ends used for actual code generation. The EDG front-end used for Intellisense won’t support variable templates in Update 2 (support is planned for Update 3). Therefore, while using compiler or STL variable templates will compile, they’ll produce red squiggles in the IDE. While unusual, we thought that this was better than artificially holding back C1XX/STL support.
Q: When was the last time that VS’s STL was caught up with the C++ Working Paper’s features?
A: I believe it was 2006, before TR1 was voted into C++0x.
Q: When was the last time you shipped STL features outside of a major version?
A: 2008 SP1, when we added TR1.
Q: C++17 sounds kinda futuristic. Are your implementations of these C++17 STL features highly experimental, or something?
A: Everything we’ve added is fully supported for production use. I’ve personally reviewed every line, and I believe it’s very high quality. Of course, the C++ Standardization Committee can change anything before final publication, but things that are voted into the C++ Working Paper tend to be relatively stable.
Q: Will all of this stuff be available in the Community Edition?
A: Yes. We have neither the ability nor the desire to offer differing levels of STL features across different editions.
Q: What’s next for the STL?
A: We’re going to work on more bugfixes, especially for performance. After that, we’ll look into implementing the rest of the Library Issues, plus any more features that are voted in, and we’ll begin to look into various Technical Specifications (no specific promises at this time).
Q: When will Update 2 be available?
A: We haven’t announced that publicly yet, but the first preview build will contain these features and will be available Soonish(TM). (Edited on 2/16/2016 to add: That first preview build, the VS 2015 Update 2 CTP, is now available. Additionally, we’ve released the compiler/library toolset as a NuGet package, see Andrew Pardoe’s post for more info.)
Q: Can I play with this stuff now?
A: Yes! We’ve updated the Visual C++ webcompiler with our current development build, so you can compile example programs and try out these features.
I’ll update this post with a download link when that preview build of Update 2 becomes available, and again for the final build. You can download the Community Edition of VS 2015 Update 1 right now, containing support for all of the purple/blue table rows above.
Special thanks to Billy O’Neal (@MalwareMinigun) and Steve Wishnousky (@SteveWishnousky), who made this possible so soon by implementing several features, issues, and bugfixes.
Stephan T. Lavavej (@StephanTLavavej)
Senior Developer – Visual C++ Libraries
0 comments