Trip Report: ISO C++ Spring 2013 Meeting

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_ptrnew 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 of a
  • 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.

Comments (17)

4 0

Arthur Langereis said on Apr 20, 2013 12:59 PM:

Thank you to all members for all your hard work! I'm looking forward to the language and library updates, popular 3rd party libraries are good breeding grounds for new ideas and it is great to see them promoted to the std namespace. There is a lot of energy right now and it is exciting to see.
0 0

AndreasPfaff said on Apr 20, 2013 01:03 PM:

great news - thank's to all!
2 0

ArashPartow said on Apr 20, 2013 01:12 PM:

Truly excellent progress!

Thanks to all those that made it happen.
7 2

alnr said on Apr 20, 2013 02:47 PM:

I really appreciate the work the comitee is doing. Especially considering C++1y looks like it actually might become C++14. However, this news is disappointing. The syntax for lambdas should be much more terse. Think lambdas in D2.0. Runtime-sized arrays are a grossly bad idea IMHO. Newbies will use them in conjunction with "for (int i = 0; i < X; ++i)" instead of std::vector and <algorithm>. Judging from the working paper (N3497), they are almost completely outside the type system (e.g. no sizeof, no type-id, not typedef, not references to, no pointers to, etc...). How is such a bolt-on feature a good idea? On a similar note: how is std::dynarray<T> not 95% the same as std::vector<T>? IMHO the difference in functionality does in no way warrant creation of a new container.

Maybe someone from the comitee could comment? I would really appreciate input as to the discussion that occured (especially regarding runtime-sized arrays).

Thanks everyone and especially Mr. Sutter again for your work.

Regards
A.L.
3 0

Grunt said on Apr 20, 2013 04:40 PM:

Very nice. I'm looking forward to the generic features.

However, I have to agree with alnr about the dynamic and runtime arrays. I am skeptical that these will bring about more benefit than grief.

Could someone recommend a user-friendly explanation of why these are being proposed? Thanks.
2 0

Ron Jones said on Apr 20, 2013 06:08 PM:

alnr: std::vector denotes dynamic resizeability. std::dynarray does not. While their interfaces/implementations look quite similar, the fact that implementations can offer std::dynarray as a stack-allocated container makes them significantly different in practice, and will (and should) end up being used in significantly different ways. I'm personally very much looking forward to them.

On the subject of lambdas, I would not expect to see any major syntactical changes as C++ progresses: we're probably stuck with it for the foreseeable future. Herb is in a much better position to comment on that, however.
0 0

LBEaston said on Apr 20, 2013 08:46 PM:

I seriously feel like a kid in a candy store.
1 0

matt said on Apr 21, 2013 06:49 AM:

Ron Jones: I'm wondering, since this sounds like an allocation policy, wouldn't adding an allocator with these properties (stack allocation allowed, non-resizable) that can be used in any standard container (incl. std::vector) be a better way to express it, also more consistent with the existing C++ practice (so far allocators were used to express allocation policy, incl. std::allocator in the Standard) and more generic (allowing to have different containers with these properties)?
1 0

derpyloves said on Apr 21, 2013 10:11 AM:

Thank you for the update, Herb.

I appreciate the progress--'make_unique' (thanks STL), and generic lambdas particularly. But frankly, I find myself rather dissappointed you make no mention yet of an important (imho) task-based concurrency improvement, namely: '.then()' non-blocking async continuations.

Without doubt, that would quickly provide a far more positive impact on our projects atm than would things like say, dynamic arrays or optional<T>.

But, I add my voice to the group to say thank you very much for all the hard work you folks on the standards committee put in!

3 0

Devid said on Apr 22, 2013 01:33 PM:

Lambdas improvements is a really good new.
Dynamic Arrays are really strange, not sure that we really need them but lest see.

So Concepts Lite are not really in C++14 but should be available a bit later, lets hope not too late.

Now C++ need Modules and Reflection/Introspection support.
IMHO compiler time Reflection/Introspection support is the most important.
7 0

bionicbeagle said on Apr 23, 2013 02:40 AM:

It's sad to see that modules don't seem to be on the list for C++14 :(

One of the main problems with C++ at scale is overall build performance and the difficulty in making tools for refactoring/analysis. Modules are absolutely required to resolve these issues, and should have been there in the 90s... yet here we are, looking at perhaps having something viable in 2020?

Also, by making unique_ptr et al pervasive and introducing generic lambdas you're really just making it worse. Personally I think core stuff like unique/shared_ptr, function etc should not be library based -- if you really see this as core constructs they should be native compiler constructs so that the compiler could make assumptions and generate smarter code - especially in debug builds. Today it's depressing to step through code making use of these things, as there is more overhead than actual relevant code. Not to mention the massive amount of work the linker has to do.

AFAICS the fact that delegates/functions aren't native means you cannot overload on lambda signatures without resorting to weird trickery, nor do type inference for lambda arguments (instead of the much more complex generic lambda construct).
2 0

Domipheus said on Apr 23, 2013 02:54 AM:

Must agree with bionicbeagle on this - I cannot disagree with anything in his comment, and the point on Modules I find myself wishing was the case on a daily basis.
0 0

Jeroen Ruigrok van der Werven said on Apr 23, 2013 03:43 AM:

I need to toss in my voice of agreement with Devid, bionicbeagle, and Domipheus for the addition of C++ modules. There is only so much replacing old build systems, such as make, with ninja or tundra can accomplish to decrease build times.
2 0

Mats Taraldsvik said on Apr 23, 2013 10:34 AM:

A huge thank you to all members pushing the C++ Standard forward! I also absolutely love that we are able to follow the progress closely through isocpp.org.

@Herb Sutter: Great to hear that there is good progress with modules. It has been silent (in terms of public/isocpp.org posts, that is) from the modules and reflection working groups. I'm waiting eagerly for the resulting paper(s)!
1 0

Ron Jones said on Apr 23, 2013 02:56 PM:

matt: std::vector implements methods that would have no meaning for runtime-sized arrays, like reserve() and resize(). Although I see no reason why it couldn't be implemented as an allocator, I don't think that would be in the best interest of users. The implementation of std::dynarray actually looks fairly straightforward anyway.

More stack-allocated container types would be welcome, but considering more complex data structures are likely to contain more data in actual practice, stack space limitations could become problematic.
0 0

Anders Sjögren said on Apr 30, 2013 02:40 AM:

Great news that C++ is moving in a much faster and more agile manner than before!

Regarding Generic lambdas:
* Will universal references be supported (by auto&&) as well?
* Will explicit template lambdas be supported as well (e.g. if non argument-type template parameters (e.g. int) are needed), and can they be combined with auto?

Regarding Lambda generalized capture:
* Will explicit types in local variable declarations be supported, making the syntax feel more like regular variable definitions?
1 1

ciqiguopimin said on May 19, 2013 06:23 AM:

So complicated docu , who can learn all new features about c++ ? it is too difficult