This afternoon in Bristol, UK, the ISO C++ standards committee adopted generic lambdas, dynamic arrays (an improved version of C99 VLAs), variable templates, reader/writer locks, make_unique
, optional<T>
, standard library user-defined literals, and a number of other language and library improvements -- and approved the result as the feature-complete Committee Draft (CD) of Standard C++14 to be distributed for its primary international review ballot.
In addition to completing the C++14 CD document, the committee also made progress on three additional important parallel specifications that are on track to be published around the same time as C++14:
- File system library (draft), based on Boost.FileSystem version 3.
- Networking library, small at first and regularly extended.
- "Concepts Lite" language extensions (draft), to express template constraints and improve template usability and error messages.
Together these mark the C++ committee’s main planned deliverables for 2014. Updated papers and an updated working draft will be available soon.
Meeting Highlights
Bristol saw a recent-record number of technical papers (160), attendees (over 100), parallel technical sessions (typically six or more subgroups meeting at once), and many overlapping evening sessions – including formal sessions that ran past midnight at least twice to resume again at 08:30.
C++14: Bug Fixes + Minor Update
C++14 is primarily a bug-fix release, but also includes new features that were ready including a number that developers have been asking for the standard to support. With the CD document contents now set to be balloted this summer, we for the first time know the shape and feature set of C++14.
To provide just a sampling, here are a few quick examples of some of the newly added features.
make_unique
One of the smallest additions is actually great in its impact. It's make_unique
:
auto u = make_unique<some_type>( constructor, parameters, here );
The reason make_unique
has important impact is that now we can teach C++ developers to mostly never use explicit new
again. In C++11 we already could teach to never use owning raw pointers and explicit delete
again, except in rare cases that are hidden inside a class in order to do something like implement a low-level data structure. However, we could not teach to never write new
because although make_shared
was provided to create a shared_ptr
, new
was still needed to create a unique_ptr
. Now, instead of “new
”, write make_unique
or make_shared
.
With draft C++14, we can say simply: Don't use owning raw pointers, new
, and delete
, except rarely when implementing low-level data structures. Allocate with make_unique
or make_shared
, use weak_ptr
where appropriate to break cycles, and don't worry about dangling pointers in C++ again.
Generic lambdas
Lambdas will now support auto
as a type name. This is convenient when the type is tedious to spell out, and is especially nice in generic code where you want the same lambda object to be usable with a variety of types. For example:
vector<int> v;
vector<shared_ptr<some_type>> index; // stores pointers to objects
// C++11:
//
for_each( begin(v), end(v), []( decltype(*begin(v))& x ) { cout << x; } );
sort( begin(index), end(index), []( shared_ptr<some_type> const& p1, shared_ptr<some_type> const& p2 ) { return *p1 < * p2; } );
auto get_size = []( unordered_multimap<wstring, list<string>> const& m ) { return m.size(); };
// C++14 draft:
//
for_each( begin(v), end(v), []( auto& x ) { cout << x; } );
sort( begin(index), end(index), []( auto const& p1, auto const& p2 ) { return *p1 < * p2; } );
auto get_size = []( auto const& m ) { return m.size(); };
// bonus: this now works with any container that supports .size()
Lambda generalized capture
Lambdas will now be able to capture by move, and define new local variables in the lambda object. For example:
auto u = make_unique<some_type>( some, parameters ); // a unique_ptr is move-only
go.run( [ u{move(u)} ] { do_something_with( u ); } ); // move the unique_ptr into the lambda
Variable templates
These can perhaps be best illustrated with an example taken right from the draft standard text (comments added).
// Write pi once for every possible type
template<typename T>
constexpr T pi = T(3.1415926535897932385);
// Sample use
template<typename T>
T circular_area(T r) {
return pi<T> * r * r;
}
Dynamic Arrays
Draft C++14 now has fixed- but runtime-sized arrays of two kinds: in the language, and as a dynarray<T>
library.
In the language, draft C++14 now allows stack-based arrays to have a size determined at run time:
void f(std::size_t n) { int a[n]; ... }
Note that this is not the same as C99 variable length arrays (VLAs), and that the C11 standard has made VLAs conditionally-supported so that they are no longer part of portable C required in a conforming C compiler. In particular, C++ explicitly not does support the following features from C99 VLAs which C++ feels are not desirable:
-
multidimensional arrays, where other than the top level has a runtime bound (in analogy, the array form of
new
expressions doesn't support that either) - modifications to the function declarator syntax
-
sizeof(a)
being a runtime-evaluated expression returning the size ofa
- typedef int a[n]; evaluating n and passing that through the typedef
In addition to stack-based runtime-sized arrays, we now also have a dynarray<T>
container in the standard library. The two features are similar, but with a few key differences: Both permit efficient allocation on the stack or on the heap, at the discretion of the implementation, but dynarray<T>
can additionally be used as a non-stack variable and in those cases will use the heap, it is inspectable with decltype
, and it supports zero-sized arrays.
optional<T>
To highlight just one more of the new features and changes, we have an evolution of Boost’s optional
type. An example tells most of the story:
cin >> s;
optional<int> o = str2int(s); // 'o' may or may not contain an int
if (o) { // does optional contain a value?
return *o; // use the value
}
On Deck: Also Targeting the '14 Timeframe
And let's end with a template checking with Concepts Lite teaser... if you write this today, what do you get?
template<typename Cont> void sort(Cont& c); list<int> lst = { 1, 3, 2, 4 }; sort(lst); // ???
Impenetrable template diagnostics. At considerable length.
What we want:
template<Sortable Cont> void sort(Cont& c); list<int> lst = { 1, 3, 2, 4 }; sort(lst); // "error: lst is not Sortable"
An implementation of the above, with about that error message, already exists.
Beyond that, consider even a "terse syntax" that would be especially helpful with generic lambdas:
void sort(Sortable& s); // possible syntax: implicit function template int main() { // and now that we have generic lambdas in the language... auto mysorter = [](Sortable& s){ /*...*/ }; // possible syntax // ... we'll surely want to constrain those too }
Interestingly, that last example shows some nice, type-checked, robust and fully generic template code, with nary a <>
in sight.
All of this is grist for the Concepts Lite Technical Specification, currently targeted for completion and publication next year.
Wrapping Up
Updated papers for these and other features, as well as an updated working draft, are expected to be available in the next two or three weeks.
Thanks again to the many committee members who worked tirelessly in preparation for this meeting, and around the clock all this past week, to achieve this milestone!
Add a Comment
Comments are closed.