VS 2015 Update 2’s STL is C++17-so-far Feature Complete

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

N3462

SFINAE-Friendly result_of

Update 2

C++17

N4387

Improving pair And tuple

Up2 Win7+

C++17

N4508

shared_mutex (Untimed)

Up2 opt-in

C++17

P0004R1

Removing Deprecated Iostreams Aliases

Update 2

C++17

P0006R0

Variable Templates For Type Traits (is_same_v, etc.)

Update 2

C++17

P0007R1

as_const()

Update 2

C++17

P0013R1

Logical Operator Type Traits (conjunction, etc.)

Update 2

C++17

P0074R0

owner_less<>

Update 2

C++17

P0092R1

<chrono> floor(), ceil(), round(), abs()

Update 2

C++17

P0156R0

Variadic lock_guard

VS 2015

C++14

N3302

constexpr For <complex>

VS 2015

C++14

N3469

constexpr For <chrono>

VS 2015

C++14

N3470

constexpr For <array>

VS 2015

C++14

N3471

constexpr For <initializer_list>, <tuple>, <utility>

VS 2015

C++14

N3545

integral_constant::operator()()

VS 2015

C++14

N3642

UDLs For <chrono>, <string> (1729ms, “meow”s, etc.)

VS 2015

C++14

N3644

Null Forward Iterators

VS 2015

C++14

N3654

quoted()

VS 2015

C++14

N3657

Heterogeneous Associative Lookup

VS 2015

C++14

N3658

integer_sequence

VS 2015

C++14

N3659

shared_mutex (Timed)

VS 2015

C++14

N3668

exchange()

VS 2015

C++14

N3669

Fixing constexpr Member Functions Without const

VS 2015

C++14

N3670

get<T>()

VS 2015

C++14

N3671

Dual-Range equal(), is_permutation(), mismatch()

VS 2015

C++14

N3778

Sized Deallocation

VS 2015

C++14

N3779

UDLs For <complex> (3.14i, etc.)

VS 2015

C++14

N3789

constexpr For <functional>

VS 2015

C++14

N3887

tuple_element_t

VS 2015

C++14

N3891

Renaming shared_mutex (Timed) To shared_timed_mutex

VS 2015

C++17

N3911

void_t

VS 2015

C++17

N4089

Safe Conversions In unique_ptr<T[]>

VS 2015

C++17

N4169

invoke()

2015 opt-in

C++17

N4190

Removing auto_ptr, random_shuffle(), And Old <functional> Stuff

VS 2015

C++17

N4258

noexcept Cleanups

VS 2015

C++17

N4259

uncaught_exceptions()

VS 2015

C++17

N4277

Trivially Copyable reference_wrapper

VS 2015

C++17

N4279

insert_or_assign()/try_emplace() For map/unordered_map

VS 2015

C++17

N4280

size(), empty(), data()

VS 2015

C++17

N4366

Precisely Constraining unique_ptr Assignment

VS 2015

C++17

N4389

bool_constant

VS 2013

C++14

N3346

Minimal Container Element Requirements

VS 2013

C++14

N3421

Transparent Operator Functors (less<>, etc.)

VS 2013

C++14

N3655

Alias Templates For <type_traits> (decay_t, etc.)

VS 2013

C++14

N3656

make_unique()

VS 2013

C++17

N4510

Supporting Incomplete Types In vector/list/forward_list

N/A

C++14

N3924

Discouraging rand()

N/A

C++17

N4284

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

Issue

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

stl@microsoft.com